[英]Merging CSV files with different headers using CSVhelper C#
嘗試使用CSVhelper將目錄中的多個.csv文件合並到一個.csv文件中時。 在目錄中有50個.csv文件,其中50個文件有兩組文件結構,一組有7列,另一組有6個。每個文件都有完全相同的前5個文件頭,但根據文件最后兩列將更改。
目錄中的每個文件都將包含這些結構中的任何一個,並且列中包含不同的數據。 新文件的輸出將包含來自所有列的數據欄操作,代碼和錯誤消息。 如果我僅使用示例1的結構文件,則文件完美地結合在一起。 但是,如果我包含具有這兩種結構的文件並嘗試在我的新文件中使用示例2中的“ErrorIPAddress”,則會收到以下錯誤:
CsvHelper.dll中發生未處理的“CsvHelper.TypeConversion.CsvTypeConverterException”類型異常
在這一行:`IEnumerable dataRecord = reader.GetRecords()。ToList();
我的問題是:如何使用一個文件中的列不在另一個文件中? 我嘗試使用以下內容進行映射: Map(m => m.ErrorIPAddress).Index(5);
而且我相信這就是導致我這個問題的路線,好像我評論它錯誤不會持續存在但顯然我不會得到我需要的數據到新的.csv。 如果我嘗試按名稱映射: Map( m => m.ErrorIPAddress ).Name( "ErrorIPAddress" );
我收到錯誤消息,表明ErrorIPAddress不在.csv文件中,因為並非所有文件都包含該列。
最終列將由格式為2的ErrorIPAddress列生成。
我假設您正在使用單個類定義,所有字段看起來像這樣:
public class StudentWebAccess
{
public int StudentID { get; set; }
public string Gender { get; set; }
public int Grade { get; set; }
public int IPAddress { get; set; } // Also ErrorIPAddress?
public DateTime DateTime { get; set; }
public string Action { get; set; }
public string Code { get; set; } // Also ErrorMessage?
}
因此,為了讀取文件格式2,您使用的是CsvClassMap,但未正確匹配屬性和字段名稱。 它應該看起來像這樣:
public class CsvFile2Map : CsvClassMap<StudentWebAccess>
{
public CsvFile2Map()
{
Map(m => m.IPAddress).Name("ErrorIPAddress");
Map(m => m.Code).Name("ErrorMessage");
}
}
如果您的類文件使用ErrorIPAddress而不是IPAddress,則必須反轉映射。
Map(m => m.ErrorIPAddress).Name("IPAddress");
您不需要外部庫。 請使用以下代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Data;
using System.Data.OleDb;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FOLDER = @"c:\temp\test";
static void Main(string[] args)
{
CSVReader reader = new CSVReader();
//table containing merged csv files
DataTable dt = new DataTable();
//get csv files one at a time
foreach (string file in Directory.GetFiles(FOLDER, "*.csv"))
{
//read csv file into a new dataset
DataSet ds = reader.ReadCSVFile(file, true);
//datatable containing new csv file
DataTable dt1 = ds.Tables[0];
//add new columns to datatable dt if doesn't exist
foreach(DataColumn col in dt1.Columns.Cast<DataColumn>())
{
//test if column exists and add if it doesn't
if (!dt.Columns.Contains(col.ColumnName))
{
dt.Columns.Add(col.ColumnName, typeof(string));
}
}
//array of column names in new table
string[] columnNames = dt1.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToArray();
//copy row from dt1 into dt
foreach(DataRow row in dt1.AsEnumerable())
{
//add new row to table dt
DataRow newRow = dt.Rows.Add();
//add data from dt1 into dt
for(int i = 0; i < columnNames.Count(); i++)
{
newRow[columnNames[i]] = row[columnNames[i]];
}
}
}
}
}
public class CSVReader
{
public DataSet ReadCSVFile(string fullPath, bool headerRow)
{
string path = fullPath.Substring(0, fullPath.LastIndexOf("\\") + 1);
string filename = fullPath.Substring(fullPath.LastIndexOf("\\") + 1);
DataSet ds = new DataSet();
try
{
//read csv file using OLEDB Net Library
if (File.Exists(fullPath))
{
string ConStr = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}" + ";Extended Properties=\"Text;HDR={1};FMT=Delimited\\\"", path, headerRow ? "Yes" : "No");
string SQL = string.Format("SELECT * FROM {0}", filename);
OleDbDataAdapter adapter = new OleDbDataAdapter(SQL, ConStr);
adapter.Fill(ds, "TextFile");
ds.Tables[0].TableName = "Table1";
}
//replace spaces in column names with underscore
foreach (DataColumn col in ds.Tables["Table1"].Columns)
{
col.ColumnName = col.ColumnName.Replace(" ", "_");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return ds;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.