web-dev-qa-db-ja.com

CsvHelperを使用してCSVからすべての値をリストに読み取ります

だから私は自分の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はおそらく独自のカスタムクラスを必要としますが、値をプリミティブ型または文字列としてのみ必要としています。また、各値が個別の文字列ではなく、行全体が単一の文字列に変換されていると思われます。

18
Ayb4btu

@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;
}
25
masinger

配列内の各行の文字列値だけが必要な場合は、パーサーを直接使用できます。

var parser = new CsvParser( textReader );
while( true )
{
    string[] row = parser.Read();
    if( row == null )
    {
        break;
    }
}

http://joshclose.github.io/CsvHelper/#reading-parsing

更新

バージョン3は、IEnumerableプロパティの読み取りと書き込みをサポートしています。

15
Josh Close

これを試してください。これは私のために働いていました。

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;
            }
        }       
    }
3
user3660719

あなたは近いです。 を文字列に変換しようとしているわけではありません。 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;
  }
}
1
Marc L.

ここでの全体のポイントは、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

0
lead