あなたが見ているサンプルは、技術的に言えば、有効な CSV 形式のファイルではありません。基本的に、ファイルを提供した人は誰でも、テキスト修飾子記号 - 二重引用符 " - を非標準的な方法で使用しました。従来の使用方法は次のとおりです。
123,"Sue said, ""Hi, this is a test!""",2012-08-15
このステートメントは次のように解析する必要があります。
Assert.AreEqual(line.Length, 3);
Assert.AreEqual(line[0], @"123");
Assert.AreEqual(line[1], @"Sue said, ""Hi, this is a test!""");
Assert.AreEqual(line[2], @"2012-08-15");
あなたの質問で提供されたサンプルCSVから、私が見た基準によると、正しい処理は基本的に引用符をテキスト修飾子ではなく文字列内の通常の文字として扱う必要があります。これが私があなたのセリフをどのように解釈するかです - もし私が間違っていたら教えてください!
Assert.AreEqual(line.Length, 6);
Assert.AreEqual(line[0], @"30: ""NY""");
Assert.AreEqual(line[1], @" 41: ""JOHN S.""");
Assert.AreEqual(line[2], @" 36: ""HAMPTON""");
Assert.AreEqual(line[3], @" 42: ""123 Road Street");
Assert.AreEqual(line[4], @" NY""");
Assert.AreEqual(line[5], @" 68: ""Y""");
テキストがテキスト修飾されているか、適切に区切られているかを判断できないため、FileHelper が壊れていると思います。これを処理するには、カスタム コードを使用することをお勧めします。Cuong Le が提供するソリューションは、あなたのソリューションに適しているようです。
参考までに、私の C# CSV ライブラリはこちらです: https://code.google.com/p/csharp-csv-reader/
編集:楽しみのために、正規表現を使用してこれをデコードできるかどうか疑問に思いました。厳密に CSV でなくても、データは一貫してフォーマットされているため、ツールボックスには別のものがある可能性があります。
String mystring = @"30: ""NY"", 41: ""JOHN S."", 36: ""HAMPTON"", 42: ""123 Road Street, NY"", 68: ""Y""
20: ""STEVE"", 12: ""JONES"", 96: ""1600 PENNSYLVANIA AVE, NW""
30: ""NY"", 41: ""JOHN S."", 36: ""HAMPTON"", 42: ""123 Road Street, NY"", 68: ""Y"", 40: 12345";
Regex r = new Regex(@"(?<id>\d*): (""(?<field>[^""]*)""|(?<field>[\d]*))");
MatchCollection mc = r.Matches(mystring);
foreach (Match m in mc) {
Console.WriteLine("{0}: {1}", m.Groups["id"], m.Groups["field"]);
}
基本的に、正規表現は 2 桁の 10 進数を探し、その後にコロン - スペース - 二重引用符が続きます。次に、別の二重引用符に到達するまで、すべてのテキストを検索します。私のテストから、これは質問で説明した両方のテスト行に対しても正しい一致を生成します。
私の正規表現が正しくない場合は、ここで利用できる気の利いたオンライン正規表現テスターがあります: http://gskinner.com/RegExr/ - データをコピーして検索領域に貼り付け、この正規表現文字列を出発点として使用してみてください:
(?<id>\d*): ("(?<field>[^"]*)"|(?<field>[\d]*))
EDIT2:以下のコメントで引用した「40:12345」の値も考慮するように正規表現を修正しました。すべての例ですべてのフィールドが正しく検出されるようになりました。
EDIT3: 別のリクエストから、この正規表現はコロンの前に無制限の長さの数字をサポートするようになりました。正規表現がどのように機能するかの簡単な説明は次のとおりです。
(?<id>\d*)
- この最初のチャンクはキャプチャ グループと呼ばれます。キャプチャ グループは括弧で囲まれています。*
10 進数 ( ) の繰り返し文字列 ( ) をキャプチャし、\d
「id」( ?<id>
) という名前を付けようとします。
:
- レコード間のコロン スペースに一致します。
"(?<field>[^"]*)"
- 開始の引用符を検索し、次に引用符 ( ) 以外の多数の文字を検索し、[^"]
別の引用符で終了します。結果を「フィールド」に保存します。
(?<field>[\d]*)
- 任意の数の 10 進数を検索し、結果を「フィールド」に保存します。一部の正規表現エンジンは、同じ名前の 2 つのキャプチャ グループを持つことをサポートしていないことに注意してください。一方を「field1」、もう一方を「field2」と呼ぶ必要があるかもしれません。