簡體   English   中英

導入兩個 CSV,從一個 CSV 添加特定列並將更改導入新的 CSV (C#)

[英]Import two CSV, add specific columns from one CSV and import changes to new CSV (C#)

我必須導入 2 個 CSV。

CSV 1 [49]:包括大約 50 個標簽分隔列。 CSV 2:[2]包含 3 列,應在我的第一個 csv 的 [3] [6] 和 [11] 位置替換。

所以繼承人我做什么:

1)導入csv並拆分為數組。

string employeedatabase = "MYPATH";


List<String> status = new List<String>();

StreamReader file2 = new System.IO.StreamReader(filename);
string line = file2.ReadLine();
while ((line = file2.ReadLine()) != null)
{
    string[] ud = line.Split('\t');
    status.Add(ud[0]);

}

String[] ud_status = status.ToArray();

問題 1:我有大約 50 個列要處理,ud_status 只是第一個,所以我需要 50 個列表和 50 個字符串數組嗎?

2)導入第二個csv並拆分成一個數組。

List<String> vorname = new List<String>();
List<String> nachname = new List<String>();
List<String> username = new List<String>();

StreamReader file = new System.IO.StreamReader(employeedatabase);
string line3 = file.ReadLine();
while ((line3 = file.ReadLine()) != null)
{
    string[] data = line3.Split(';');
    vorname.Add(data[0]);
    nachname.Add(data[1]);
    username.Add(data[2]);
}

String[] db_vorname = vorname.ToArray();
String[] db_nachname = nachname.ToArray();
String[] db_username = username.ToArray();

問題 2:加載這兩個 csv 后,我不知道如何組合它們,並更改為如上所述的列..

像這樣的東西?

mynewArray = ud_status + "/t" + ud_xy[..n] + "/t" + changed_colum + ud_xy[..n];

使用編碼“utf-8”將“mynewarray”保存到制表器分隔的csv中。

要將文件讀入有意義的格式,您應該設置一個定義 CSV 格式的類:

public class CsvRow
{
    public string vorname { get; set; }
    public string nachname { get; set; }
    public string username { get; set; }
    public CsvRow (string[] data)
    {
         vorname = data[0];
         nachname = data[1];
         username = data[2];
    }
}

然后填充一個列表:

List<CsvRow> rows = new List<CsvRow>();

StreamReader file = new System.IO.StreamReader(employeedatabase);
string line3 = file.ReadLine();
while ((line3 = file.ReadLine()) != null)
{
    rows.Add(new CsvRow(line3.Split(';'));
}

類似地格式化您的其他 CSV 並為新字段包含未使用的屬性。 加載兩者后,您可以循環填充此列表中的新屬性,通過 CSV 希望共享的任何公共字段匹配記錄。 然后最終將結果數據輸出到一個新的 CSV 文件。

您的解決方案不是使用string數組來執行此操作。 那只會讓你發瘋。 最好使用System.Data.DataTable對象。

我沒有機會在此結尾處測試 LINQ lambda 表達式(或實際上任何一個,我在休息時寫的),但它應該讓您走上正軌。

using (var ds = new System.Data.DataSet("My Data"))
        {
            ds.Tables.Add("File0");
            ds.Tables.Add("File1");
            string[] line;
            using (var reader = new System.IO.StreamReader("FirstFile"))
            {                       
                //first we get columns for table 0                    
                foreach (string s in reader.ReadLine().Split('\t'))
                    ds.Tables["File0"].Columns.Add(s);
                while ((line = reader.ReadLine().Split('\t')) != null)
                {
                    //and now the rest of the data. 
                    var r = ds.Tables["File0"].NewRow();
                    for (int i = 0; i <= line.Length; i++)
                    {
                        r[i] = line[i];
                    }
                    ds.Tables["File0"].Rows.Add(r);
                }                   
            }
            //we could probably do these in a loop or a second method,
            //but you may want subtle differences, so for now we just do it the same way 
            //for file1
            using (var reader2 = new System.IO.StreamReader("SecondFile"))
            {
                foreach (string s in reader2.ReadLine().Split('\t'))
                    ds.Tables["File1"].Columns.Add(s);
                while ((line = reader2.ReadLine().Split('\t')) != null)
                {
                    //and now the rest of the data. 
                    var r = ds.Tables["File1"].NewRow();
                    for (int i = 0; i <= line.Length; i++)
                    {
                        r[i] = line[i];
                    }
                    ds.Tables["File1"].Rows.Add(r);
                }
            }
            //you now have these in functioning datatables. Because we named columns, 
            //you can call them by name specifically, or by index, to replace in the first datatable. 
            string[] columnsToReplace = new string[] { "firstColumnName", "SecondColumnName", "ThirdColumnName" };
            for(int i = 0; i < ds.Tables[0].Rows.Count; i++)
            {
                //you didn't give a sign of any relation between the two tables
                //so this is just by row, and assumes the row count is equivalent.
                //This is also not advised. 
                //if there is a key these sets of data share
                //you should join on them instead. 
                foreach(DataRow dr in ds.Tables[0].Rows[i].ItemArray)
                {
                    dr[3] = ds.Tables[1].Rows[i][columnsToReplace[0]];
                    dr[6] = ds.Tables[1].Rows[i][columnsToReplace[1]];
                    dr[11] = ds.Tables[1].Rows[i][columnsToReplace[2]];
                }
            }
            //ds.Tables[0] now has the output you want.  
            string output = String.Empty;
            foreach (var s in ds.Tables[0].Columns)
               output = String.Concat(output, s ,"\t");
            output = String.Concat(output, Environment.NewLine); // columns ready, now the rows. 
            foreach (DataRow r in ds.Tables[0].Rows)
               output = string.Concat(output, r.ItemArray.SelectMany(t => (t.ToString() + "\t")), Environment.NewLine);
            if(System.IO.File.Exists("MYPATH"))
                using (System.IO.StreamWriter file = new System.IO.StreamWriter("MYPATH")) //or a variable instead of string literal
                {                  
                    file.Write(output);
                }

        }

使用Cinchoo ETL - 一個開源文件助手庫,您可以按如下方式合並 CSV 文件。 假設 2 個 CSV 文件包含相同數量的行。

string CSV1 = @"Id  Name    City
1   Tom New York
2   Mark    FairFax";

string CSV2 = @"Id  City
1   Las Vegas
2   Dallas";

dynamic rec1 = null;
dynamic rec2 = null;
StringBuilder csv3 = new StringBuilder();
using (var csvOut = new ChoCSVWriter(new StringWriter(csv3))
    .WithFirstLineHeader()
    .WithDelimiter("\t")
    )
{
    using (var csv1 = new ChoCSVReader(new StringReader(CSV1))
        .WithFirstLineHeader()
        .WithDelimiter("\t")
        )
    {
        using (var csv2 = new ChoCSVReader(new StringReader(CSV2))
            .WithFirstLineHeader()
            .WithDelimiter("\t")
            )
        {
            while ((rec1 = csv1.Read()) != null && (rec2 = csv2.Read()) != null)
            {
                rec1.City = rec2.City;
                csvOut.Write(rec1);
            }
        }
    }
}
Console.WriteLine(csv3.ToString());

希望能幫助到你。

免責聲明:我是這個庫的作者。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM