CSVでダブルクォーテーションを使用する場合はエスケープしなければいけません
勘定科目コード,補助科目コード,当月残高(機能通貨),GL記帳日,メモ
1234567890,100,1,8月13日,あいうえお
1234567890,100,1,8月13日,あいうえお"かきくけこ"
この例であれば
1234567890,100,1,8月13日,"あいうえお""かきくけこ"""
こうしなければ不正なデータと判定されてしまうと思います
C#を勉強しています。
C#のWindowsFormで、CSVファイルを読み込むんで表示するプログラムを作っています。
CSVの読み込みにはCSVHelperというライブラリが有用との情報を得て、CSVHelper(ver27)を利用しています。
CSVデータにダブルクオーテーションがない場合は読み込めたのですが、CSVデータにダブルクオーテーションがあると読み込めません。以下のエラーメッセージが出現します。
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CsvHelper;
using CsvHelper.Configuration;
using CsvHelper.Configuration.Attributes;
using System.IO;
using System.Globalization;
namespace CSVReadForm4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
List<S> records;
using (var streamReader = new StreamReader(@"ファイルパス"))
using (var csvReader = new CsvReader(streamReader, CultureInfo.InvariantCulture))
{
records = csvReader.GetRecords<S>().ToList();
}
dataGridView1.DataSource = records;
}
}
public class S
{
[Name("AAA")]
public string aaa { get; set; }
[Name("BBB")]
public string bbb { get; set; }
[Name("CCC")]
public long ccc { get; set; }
[Name("DDD")]
public DateTime ddd { get; set; }
}
}
### 自分で試したこと
CSVHelperのConfigurationの設定でなんとかならないか試しましたが、うまくいきませんでした。
ダブルクオーテーションは取り除かれてしまってもかまいません。どなたかご教示をお願いします。
CSVでダブルクォーテーションを使用する場合はエスケープしなければいけません
勘定科目コード,補助科目コード,当月残高(機能通貨),GL記帳日,メモ
1234567890,100,1,8月13日,あいうえお
1234567890,100,1,8月13日,あいうえお"かきくけこ"
この例であれば
1234567890,100,1,8月13日,"あいうえお""かきくけこ"""
こうしなければ不正なデータと判定されてしまうと思います
@yukatanoyutaka
Questioner@yukatanoyutaka
Questioner@yukatanoyutaka
Questioner読もうとしているCSVファイルがRFC4180に反していることはわかっていて、引用符をすべて無視してでもいいからそのファイルを読み込みたいという話だと思います。
リファレンスマニュアル的なものが用意されていないのでCSVHelperでどうすればいいかわかりませんが、それならファイルの内容を加工してからCSVHelperに渡すという作戦もあります。
/// <summary>
/// 元ストリームから二重引用符を除去したストリーム
/// </summary>
/// <remarks>ASCIIまたはUTF-8エンコードしか考慮していない</remarks>
public class DQuoteRemoveStream : System.IO.MemoryStream
{
private const byte DQUOTE = (byte)'"';
public DQuoteRemoveStream(System.IO.Stream sourceStream) : base((int)sourceStream.Length)
{
var buffer = new byte[8192];
int readbytes;
int st = 0, len=0;
while ((readbytes = sourceStream.Read(buffer)) > 0)
{
while (st + len < readbytes)
{
if (buffer[st + len] != DQUOTE)
{ len++; }
else
{
if (len > 0)
{ this.Write(new ReadOnlySpan<byte>(buffer, st, len)); }
st += len + 1;
len = 0;
}
}
}
if (len > 0)
{ this.Write(new ReadOnlySpan<byte>(buffer, st, len)); }
this.SetLength(st + len);
this.Seek(0, System.IO.SeekOrigin.Begin);
}
}
動作確認していませんが、CSVHelperに渡すストリームをこれにすれば
効率は悪いけどCSVHelperの設定に悩むよりは手っ取り早いかと思います。
@yukatanoyutaka
Questioner