単純なインポートアプリケーションを作成しており、CSVファイルを読み取り、DataGrid
に結果を表示し、CSVファイルの破損した行を別のグリッドに表示する必要があります。たとえば、別のグリッドに5つの値よりも短い線を表示します。私はこのようにしようとしています:
StreamReader sr = new StreamReader(FilePath);
importingData = new Account();
string line;
string[] row = new string [5];
while ((line = sr.ReadLine()) != null)
{
row = line.Split(',');
importingData.Add(new Transaction
{
Date = DateTime.Parse(row[0]),
Reference = row[1],
Description = row[2],
Amount = decimal.Parse(row[3]),
Category = (Category)Enum.Parse(typeof(Category), row[4])
});
}
ただし、この場合、配列を操作することは非常に困難です。値を分割するより良い方法はありますか?
車輪を再発明しないでください。すでに.NET BCLにあるものを活用してください。
Microsoft.VisualBasic
への参照を追加します(はい、VisualBasicと表示されますが、C#でも同様に動作します-最後はすべてILであることに注意してください)Microsoft.VisualBasic.FileIO.TextFieldParser
クラスを使用してCSVファイルを解析しますサンプルコードは次のとおりです。
using (TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv"))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
//Processing row
string[] fields = parser.ReadFields();
foreach (string field in fields)
{
//TODO: Process field
}
}
}
私のC#プロジェクトではとても便利です。
他のリンク/情報は次のとおりです。
私の経験では、多くの異なるcsv形式があります。特に、フィールド内の引用符と区切り文字のエスケープ処理方法。
これらは私が遭遇した亜種です:
私は既存のcsvパーサーの多くを試しましたが、私が遭遇したバリアントを処理できる単一のパーサーはありません。また、パーサーがサポートするバリアントをエスケープするドキュメントから見つけることも困難です。
私のプロジェクトでは、VB TextFieldParserまたはカスタムスプリッターを使用しています。
NugetのCsvHelper をお勧めします。
(Microsoft.VisualBasicへの参照を追加すると、気分が悪くなります。見苦しいだけでなく、おそらくクロスプラットフォームでもありません。)
車輪の再発明をしたくない場合、ライブラリを使用するのがクールな場合もありますが、この場合、ライブラリを使用する場合と比較して、より少ないコード行で読みやすい同じジョブを実行できます。ここに私が非常に使いやすいと思う別のアプローチがあります。
using (StreamReader reader = new StreamReader(fileName))
{
string line;
while ((line = reader.ReadLine()) != null)
{
//Define pattern
Regex CSVParser = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
//Separating columns to array
string[] X = CSVParser.Split(line);
/* Do something with X */
}
}
CSVは複雑になりますreal高速。
堅牢で十分にテストされたものを使用します。
FileHelpers: www.filehelpers.net
FileHelpersは、ファイル、文字列、またはストリーム内の固定長または区切りレコードからデータをインポート/エクスポートするための無料で使いやすい.NETライブラリです。
私はこれをここで使用します:
http://www.codeproject.com/KB/database/GenericParser.aspx
前回このようなものを探していたとき、これに対する答えとしてそれを見つけました question 。
このリストのもう1つ、 Cinchoo ETL -CSVファイルを読み書きするためのオープンソースライブラリ
以下のサンプルCSVファイルの場合
Id, Name
1, Tom
2, Mark
以下のようにライブラリを使用してすばやく読み込むことができます
using (var reader = new ChoCSVReader("test.csv").WithFirstLineHeader())
{
foreach (dynamic item in reader)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
}
CSVファイルに一致するPOCOクラスがある場合
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
以下のように使用してCSVファイルをロードできます
using (var reader = new ChoCSVReader<Employee>("test.csv").WithFirstLineHeader())
{
foreach (var item in reader)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
}
CodeProject の記事をご覧ください。
免責事項:私はこのライブラリの著者です
private static DataTable ConvertCSVtoDataTable(string strFilePath)
{
DataTable dt = new DataTable();
using (StreamReader sr = new StreamReader(strFilePath))
{
string[] headers = sr.ReadLine().Split(',');
foreach (string header in headers)
{
dt.Columns.Add(header);
}
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(',');
DataRow dr = dt.NewRow();
for (int i = 0; i < headers.Length; i++)
{
dr[i] = rows[i];
}
dt.Rows.Add(dr);
}
}
return dt;
}
private static void WriteToDb(DataTable dt)
{
string connectionString =
"Data Source=localhost;" +
"Initial Catalog=Northwind;" +
"Integrated Security=SSPI;";
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("spInsertTest", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@policyID", SqlDbType.Int).Value = 12;
cmd.Parameters.Add("@statecode", SqlDbType.VarChar).Value = "blagh2";
cmd.Parameters.Add("@county", SqlDbType.VarChar).Value = "blagh3";
con.Open();
cmd.ExecuteNonQuery();
}
}
}
前の回答を完了するには、CSVファイルのオブジェクトのコレクションが必要になる場合があります。CSVファイルは、TextFieldParser
メソッドまたはstring.Split
メソッドで解析され、Reflectionを介して各行がオブジェクトに変換されます。明らかに、最初にCSVファイルの行に一致するクラスを定義する必要があります。
ここにあるMichael KropatのシンプルなCSV Serializerを使用しました: Generic class to CSV(すべてのプロパティ) そして彼のメソッドを再利用して、希望するクラスのフィールドとプロパティを取得しました。
次の方法でCSVファイルをデシリアライズします。
public static IEnumerable<T> ReadCsvFileTextFieldParser<T>(string fileFullPath, string delimiter = ";") where T : new()
{
if (!File.Exists(fileFullPath))
{
return null;
}
var list = new List<T>();
var csvFields = GetAllFieldOfClass<T>();
var fieldDict = new Dictionary<int, MemberInfo>();
using (TextFieldParser parser = new TextFieldParser(fileFullPath))
{
parser.SetDelimiters(delimiter);
bool headerParsed = false;
while (!parser.EndOfData)
{
//Processing row
string[] rowFields = parser.ReadFields();
if (!headerParsed)
{
for (int i = 0; i < rowFields.Length; i++)
{
// First row shall be the header!
var csvField = csvFields.Where(f => f.Name == rowFields[i]).FirstOrDefault();
if (csvField != null)
{
fieldDict.Add(i, csvField);
}
}
headerParsed = true;
}
else
{
T newObj = new T();
for (int i = 0; i < rowFields.Length; i++)
{
var csvFied = fieldDict[i];
var record = rowFields[i];
if (csvFied is FieldInfo)
{
((FieldInfo)csvFied).SetValue(newObj, record);
}
else if (csvFied is PropertyInfo)
{
var pi = (PropertyInfo)csvFied;
pi.SetValue(newObj, Convert.ChangeType(record, pi.PropertyType), null);
}
else
{
throw new Exception("Unhandled case.");
}
}
if (newObj != null)
{
list.Add(newObj);
}
}
}
}
return list;
}
public static IEnumerable<MemberInfo> GetAllFieldOfClass<T>()
{
return
from mi in typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
where new[] { MemberTypes.Field, MemberTypes.Property }.Contains(mi.MemberType)
let orderAttr = (ColumnOrderAttribute)Attribute.GetCustomAttribute(mi, typeof(ColumnOrderAttribute))
orderby orderAttr == null ? int.MaxValue : orderAttr.Order, mi.Name
select mi;
}
まず、CSVとは何か、それをどのように記述するかを理解する必要があります。
/r/n
)は次の「テーブル」行です。\t
または,
です/r/n
記号を含めることができます(この場合、セルは引用符で始まり、この記号で終わる必要があります)C#/ Visual BasicがCSVファイルを操作する最も簡単な方法は、標準のMicrosoft.VisualBasic
ライブラリを使用することです。必要な参照と次の文字列をクラスに追加するだけです。
using Microsoft.VisualBasic.FileIO;
はい、C#で使用できます。心配しないでください。このライブラリは比較的大きなファイルを読み取ることができ、必要なすべてのルールをサポートしているため、すべてのCSVファイルを操作できます。
少し前に、このライブラリに基づいてCSV読み取り/書き込み用の簡単なクラスを作成しました。この単純なクラスを使用すると、2次元配列のようにCSVを操作できます。次のリンクでクラスを見つけることができます: https://github.com/ukushu/DataExporter
使用の簡単な例:
Csv csv = new Csv("\t");//delimiter symbol
csv.FileOpen("c:\\file1.csv");
var row1Cell6Value = csv.Rows[0][5];
csv.AddRow("asdf","asdffffff","5")
csv.FileSave("c:\\file2.csv");