解析する必要がある非常に不十分な Csv ファイルがいくつかあります。私は CsvHelper を使用していますが、うまく機能しています。ただし、通常は二重の空白がある行がいくつかあります。
ファイル:
Text,SomeDouble,MoreText
"良い",1.23,"良い"
「悪い」、「悪い」
これをマッピングしようとすると
public class Test
{
[CsvField(Name = "Text")]
public string Text { get; set; }
[CsvField(Name = "SomeDouble")]
public double? SomeDouble{ get; set; }
[CsvField(Name = "MoreText")]
public string MoreText{ get; set; }
}
次に、次のようなエラーが表示されます。
CsvHelper.CsvReaderException: タイプのレコードを読み取ろうとしてエラーが発生しました
行: '2' (1 ベース)
フィールド インデックス: '1' (0 ベース)
フィールド名: 'SomeDouble'
フィールド値: ' '
System.Exception: は Double の有効な値ではありません。---> System.FormatException: 入力文字列が正しい形式ではありませんでした。
System.Number.ParseDouble (文字列値、NumberStyles オプション、NumberFormatInfo numfmt) で System.ComponentModel.DoubleConverter.FromString (文字列値、NumberFormatInfo formatInfo) で System.ComponentModel.BaseNumberConverter.ConvertFrom (ITypeDescriptorContext コンテキスト、CultureInfo カルチャ、オブジェクト値) - -- 内部例外スタック トレースの終わり --- System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext コンテキスト、CultureInfo カルチャ、オブジェクト値) で System.ComponentModel.NullableConverter.ConvertFrom(ITypeDescriptorContext コンテキスト、CultureInfo カルチャ、オブジェクト値) で lambda_method( Closure 、 ICsvReader ) CsvHelper.CsvReader.d__0`1.MoveNext() で
私の考えでは、カスタム パーサーを作成するか、値を文字列プロパティにマップしてそこで解析を行うという選択肢があります。
他のオプションはありますか?
空白をnullとして扱いたいという設定ができればいいのですが。
リクエストに応じて、問題を再現するコード サンプルを次に示します。
static class Program
{
public class Test
{
[CsvField(Name = "Text")]
public string Text { get; set; }
[CsvField(Name = "SomeDouble")]
public double? SomeDouble { get; set; }
[CsvField(Name = "MoreText")]
public string MoreText { get; set; }
}
static void Main(string[] args)
{
// create fake in memory file
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);
streamWriter.WriteLine("Text,SomeDouble,MoreText");
streamWriter.WriteLine("Good, 1.23, Good");
streamWriter.WriteLine("Bad, ,Bad");
streamWriter.Flush();
//reset the file to the begining
memoryStream.Position = 0;
using (
var csv =
new CsvReader(
new StreamReader(memoryStream)))
{
// this call will blow up with the exception.
var records = csv.GetRecords<Test>().ToList();
//carry on and do stuff with 'records'...
}
}
ありがとう。