だから私は自分のCSVリーダー/ライターを書くべきではないことを読んでいたので、nugetを介してインストールされたCsvHelperライブラリを使用しようとしました。 CSVファイルはグレースケールの画像で、行の数が画像の高さで、列の数が幅です。値を行単位で単一の_List<string>
_または_List<byte>
_に読み取りたいです。
私がこれまでに持っているコードは次のとおりです。
_using CsvHelper;
public static List<string> ReadInCSV(string absolutePath)
{
IEnumerable<string> allValues;
using (TextReader fileReader = File.OpenText(absolutePath))
{
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
allValues = csv.GetRecords<string>
}
return allValues.ToList<string>();
}
_
しかし、allValues.ToList<string>()
は以下をスローしています:
CsvConfigurationExceptionはユーザーコードによって処理されませんでした
CsvHelper.dllでタイプ 'CsvHelper.Configuration.CsvConfigurationException'の例外が発生しましたが、ユーザーコードでは処理されませんでした
追加情報:IEnumerableを継承する型は自動マッピングできません。レコードのリストに作用するGetRecordsまたはWriteRecordsを呼び出す代わりに、誤って単一のレコードに作用するGetRecordまたはWriteRecordを呼び出しましたか?
GetRecords
はおそらく独自のカスタムクラスを必要としますが、値をプリミティブ型または文字列としてのみ必要としています。また、各値が個別の文字列ではなく、行全体が単一の文字列に変換されていると思われます。
@Marc Lの投稿によると、これを試すことができます:
public static List<string> ReadInCSV(string absolutePath) {
List<string> result = new List<string>();
string value;
using (TextReader fileReader = File.OpenText(absolutePath)) {
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
while (csv.Read()) {
for(int i=0; csv.TryGetField<string>(i, out value); i++) {
result.Add(value);
}
}
}
return result;
}
配列内の各行の文字列値だけが必要な場合は、パーサーを直接使用できます。
var parser = new CsvParser( textReader );
while( true )
{
string[] row = parser.Read();
if( row == null )
{
break;
}
}
http://joshclose.github.io/CsvHelper/#reading-parsing
更新
バージョン3は、IEnumerableプロパティの読み取りと書き込みをサポートしています。
これを試してください。これは私のために働いていました。
TextReader reader = File.OpenText(filePath);
CsvReader csvFile = new CsvReader(reader);
csvFile.Configuration.HasHeaderRecord = true;
csvFile.Read();
var records = csvFile.GetRecords<Server>().ToList();
サーバーはエンティティクラスです。これが私が作成した方法です。
public class Server
{
private string details_Table0_ProductName;
public string Details_Table0_ProductName
{
get
{
return details_Table0_ProductName;
}
set
{
this.details_Table0_ProductName = value;
}
}
private string details_Table0_Version;
public string Details_Table0_Version
{
get
{
return details_Table0_Version;
}
set
{
this.details_Table0_Version = value;
}
}
}
あなたは近いです。 行を文字列に変換しようとしているわけではありません。 CsvHelperは、ヘッダー行で指定された名前を使用して、行の各フィールドを指定したタイプのプロパティにマップしようとします。さらに、IEnumerable
型(string
が実装する)を使用してこれを行う方法を理解していないため、型のテストで自動マッピングがそのポイントに達するとスローされます。
それは、あなたがしていることにとって非常に複雑なことです。ファイル形式が非常にシンプルで、よく知られているフィールド形式であり、エスケープも引用符も使用されていない区切り文字である場合、ライブラリをインポートするオーバーヘッドを引き受ける必要がある理由はわかりません。 System.IO.File.ReadLines()
およびString.Split()
を使用して、必要に応じて値を列挙できるはずです。
//pseudo-code...you don't need CsvHelper for this
IEnumerable<string> GetFields(string filepath)
{
foreach(string row in File.ReadLines(filepath))
{
foreach(string field in row.Split(',')) yield return field;
}
}
ここでの全体のポイントは、CSVのすべての行を読み取り、オブジェクトのコレクションに非シリアル化することです。なぜ文字列のコレクションとして読みたいのか分かりません。前述のように、一般的なReadAll()はおそらくその場合に最適です。このライブラリは、その目的で使用すると輝いています。
using System.Linq;
...
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader))
{
var yourList = csv.GetRecords<YourClass>().ToList();
}
ToList()を使用しない場合-一度に1つのレコードを返します(パフォーマンスを向上させるため)。 https://joshclose.github.io/CsvHelper/examples/reading/enumerate-classをお読みください。 -records