C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

CSVHelperでのクウォート混在フィールド

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■84502 / inTopicNo.1)  CSVHelperでのクウォート混在フィールド
  
□投稿者/ coco (1回)-(2017/07/08(Sat) 18:12:07)

分類:[.NET 全般] 

C# CSVHelper利用

CSVHelperを利用したCSVファイル出力をおこなっています。
その際に文字列はダブルクウォート(")で囲み、整数はそのまま出力したいのですが、
希望した結果になりません。
Configuration.QuoteAllFieldsを指定してすべてのフィールドをダブルクウォートで囲むか
どうかの指定は行えるのですが、個々に設定する方法はないのでしょうか?


class Foo
{
    public string A {get; set;}
    public string B {get; set;}
    public int C {get; set;}
}

Foo foo = new Foo() 
{
    A = "aaa",
    B = "bb ",   // ← 先頭・末尾に空白がある場合のみ、自動的にクウォートが付与される
    C = 123,
};
using (FileStream rfs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite))
{
    using (StreamWriter writer = new StreamWriter(rfs))
    {
        using (var csvWriter = new CsvWriter(writer))
        {
      csvWriter.WriteRecord<Foo>(foo);
        }
    }
}

//// 出力 ////
aaa,"bb ",123

引用返信 編集キー/
■84505 / inTopicNo.2)  Re[1]: CSVHelperでのクウォート混在フィールド
□投稿者/ shu (1035回)-(2017/07/10(Mon) 10:08:23)
No84502 (coco さん) に返信

CSVHelperを使用したことはありませんが
全ての項目に"を付加するかしないかしかないのであれば
出力用に"を付加した文字列を設定するかPropertyの戻りが
"付になるようにするなどしてみはどうでしょうか?
引用返信 編集キー/
■84507 / inTopicNo.3)  Re[2]: CSVHelperでのクウォート混在フィールド
□投稿者/ kaina (27回)-(2017/07/10(Mon) 14:17:34)
私もCSVHelperを使用したことはありませんが、
公式ドキュメントを流し読みしたら、
TypeConverterOptionで設定出来るんじゃないかな。

公式ドキュメント
https://joshclose.github.io/CsvHelper/

間違ってたらごめんなさい。
引用返信 編集キー/
■84515 / inTopicNo.4)  Re[3]: CSVHelperでのクウォート混在フィールド
□投稿者/ coco (2回)-(2017/07/11(Tue) 16:09:20)
No84507 (kaina さん) に返信
> 私もCSVHelperを使用したことはありませんが、
> 公式ドキュメントを流し読みしたら、
> TypeConverterOptionで設定出来るんじゃないかな。
>
> 公式ドキュメント
> https://joshclose.github.io/CsvHelper/
>
> 間違ってたらごめんなさい。

文字列に事前にクウォーを付加するようにTypeConverterを作成してみたのですが、
クウォートと付与したフィールドがダブルクウォートが3連続で出力されるという
こちらの想定を超える、挙動となってしまいます。


==== 以下のようになるようにTypeConverterを実装 =======
Foo foo = new Foo() 
{
A = "\"aaa\"", // TypeConverterにてクウォートを付与
B = ""bb "", // 自動的にクウォートが付与されるため、未加工
C = 123, // 数値のため、未加工
};

//// 出力 ////
"""aaa""","bb ",123

引用返信 編集キー/
■84517 / inTopicNo.5)  Re[4]: CSVHelperでのクウォート混在フィールド
□投稿者/ ペリー (1回)-(2017/07/11(Tue) 16:47:23)
Aの内容が二重引用符を含む"aaa"でよいのであれば、
CSVの出力結果は"""aaa"""で正しいです。

外側の引用符は文字列を表す区切り文字
2番目・3番目の引用符は二つ重ねることで引用符文字1文字を表す(エスケープ)
引用返信 編集キー/
■84518 / inTopicNo.6)  Re[5]: CSVHelperでのクウォート混在フィールド
□投稿者/ kaina (28回)-(2017/07/11(Tue) 17:25:14)
ペリーさんが書かれている通り、CSVの仕様としては正しい動きです。

以下のページにCSVの一般的書式の仕様が書かれているRFC4180の翻訳があります。

http://www.kasai.fm/wiki/rfc4180jp

以下抜粋でこのように書かれています。

7. If double-quotes are used to enclose fields, then a double-quote
appearing inside a field must be escaped by preceding it with
another double quote. For example:

7. フィールドがダブルクォーテーションで囲まれている場合、フィールドの値に含まれるダブルクォーテーションは、
その直前にひとつダブルクォーテーションを付加して、エスケープしなければならない。例えば、

"aaa","b""bb","ccc"


引用返信 編集キー/
■84519 / inTopicNo.7)  Re[6]: CSVHelperでのクウォート混在フィールド
□投稿者/ coco (3回)-(2017/07/11(Tue) 18:23:31)
No84518 (kaina さん) に返信
> ペリーさんが書かれている通り、CSVの仕様としては正しい動きです。
>
> 以下のページにCSVの一般的書式の仕様が書かれているRFC4180の翻訳があります。
>
> http://www.kasai.fm/wiki/rfc4180jp
>
> 以下抜粋でこのように書かれています。
>
> 7. If double-quotes are used to enclose fields, then a double-quote
> appearing inside a field must be escaped by preceding it with
> another double quote. For example:
>
> 7. フィールドがダブルクォーテーションで囲まれている場合、フィールドの値に含まれるダブルクォーテーションは、
> その直前にひとつダブルクォーテーションを付加して、エスケープしなければならない。例えば、
>
> "aaa","b""bb","ccc"
>
>

CSVの仕様と私の期待する結果を一緒に論じ、不備がございました。もうしわけございません。
当方の期待する動作としては、文字列部はすべて固定長であり空白部を含めてクウォートで囲み
整数部はそのまま、出力したいです。

(期待結果)
"aaa","bbb ",ccc // 文字列のみダブルクウォートで囲む

ただ、色々と試してはいるのですが、以下のように望む結果となっておりません。
"aaa","bbb ","ccc" // QuoteAllFields TRUEの場合(cccはダブルクウォートで囲みたくない)
"aaa", "bbb " ,ccc  // QuoteAllFields FALSEにし、Quoteを' 'に設定した上で、事前にクウォートをエスケープした場合(Delimiterの前後の空白がシステム的にNG)




引用返信 編集キー/
■84520 / inTopicNo.8)  Re[7]: CSVHelperでのクウォート混在フィールド
□投稿者/ もりお (41回)-(2017/07/11(Tue) 22:20:12)
No84519 (coco さん) に返信

クオートを指定できるWriteFieldメソッドが公開されていますので
CsvWriterを拡張してしまえばできるのでしょうけれども
なんかもっと簡単なやり方があってもよさそうな気がしますね。

class CustomWriter<T>
{
    List<string> propertyNames = new List<string>();
    Dictionary<string, bool> shouldQuotes = new Dictionary<string, bool>();
    CsvWriter csvWriter;

    public CustomWriter(CsvWriter writer)
    {
        foreach (var property in typeof(T).GetProperties())
        {
            propertyNames.Add(property.Name);
            shouldQuotes.Add(property.Name, property.PropertyType == typeof(string));
        }

        this.csvWriter = writer;
    }

    public void writeRecord(T obj)
    {
        foreach (var propertyName in propertyNames)
        {
            var field = typeof(T).GetProperty(propertyName).GetValue(obj).ToString();
            var shouldQuote = shouldQuotes[propertyName];
            csvWriter.WriteField(field, shouldQuote);
        }

        csvWriter.NextRecord();
    }
}

引用返信 編集キー/
■84522 / inTopicNo.9)  Re[8]: CSVHelperでのクウォート混在フィールド
□投稿者/ coco (4回)-(2017/07/12(Wed) 09:12:16)
No84520 (もりお さん) に返信
> ■No84519 (coco さん) に返信
> 
> クオートを指定できるWriteFieldメソッドが公開されていますので
> CsvWriterを拡張してしまえばできるのでしょうけれども
> なんかもっと簡単なやり方があってもよさそうな気がしますね。
> 
> class CustomWriter<T>
> {
>     List<string> propertyNames = new List<string>();
>     Dictionary<string, bool> shouldQuotes = new Dictionary<string, bool>();
>     CsvWriter csvWriter;
> 
>     public CustomWriter(CsvWriter writer)
>     {
>         foreach (var property in typeof(T).GetProperties())
>         {
>             propertyNames.Add(property.Name);
>             shouldQuotes.Add(property.Name, property.PropertyType == typeof(string));
>         }
> 
>         this.csvWriter = writer;
>     }
> 
>     public void writeRecord(T obj)
>     {
>         foreach (var propertyName in propertyNames)
>         {
>             var field = typeof(T).GetProperty(propertyName).GetValue(obj).ToString();
>             var shouldQuote = shouldQuotes[propertyName];
>             csvWriter.WriteField(field, shouldQuote);
>         }
> 
>         csvWriter.NextRecord();
>     }
> }
> 

ご指南ありがとうございます。
ご提示頂いた方法にて、対応していこうと思います。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ