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

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

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

Re[4]: TextFieldParserでCSVファイル取り込み


(過去ログ 121 を表示中)

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

■72634 / inTopicNo.1)  TextFieldParserでCSVファイル取り込み
  
□投稿者/ シルバ (1回)-(2014/07/01(Tue) 10:11:25)

分類:[.NET 全般] 

分類:[VB.NET/VB2005 以降] 

環境:VS2012(VB)
OS:Windows8.1pro

クライアントから送られてきたCSVファイルをTextFieldParserで取り込んでいるのですが、
取り込むCSVファイルの文字列の中にダブルクォーテーション(")が1つしか入っていないデータがあり、
うまく取り込むことができません。

本来CSVの仕様としてはダブルクォーテーション(")を文字として扱うときは2つ記述するべきなのですが
クライアントの仕様により、CSVファイルは変更できないようです。

改行も含まれているのでTextFieldParserを使いたいのですが何か良い方法はないでしょうか?
よろしくお願いします。

[例]
"AAA","BB"C"DD","EE"
    ↓
AAA
BB"C"DD
EE
引用返信 編集キー/
■72635 / inTopicNo.2)  間違えました
□投稿者/ INO (1回)-(2014/07/01(Tue) 10:12:19)
2014/07/01(Tue) 10:15:01 編集(投稿者)
2014/07/01(Tue) 10:14:57 編集(投稿者)

間違えました
引用返信 編集キー/
■72650 / inTopicNo.3)  Re[1]: TextFieldParserでCSVファイル取り込み
□投稿者/ 魔界の仮面弁士 (38回)-(2014/07/01(Tue) 15:35:53)
No72634 (シルバ さん) に返信
> TextFieldParserを使いたいのですが何か良い方法はないでしょうか?
TextFieldParser では対応できないはずです。
面倒ですが、互換クラスを自作するなどして対応することになるかと。


> 本来CSVの仕様としてはダブルクォーテーション(")を文字として扱うときは2つ記述するべき
まぁ、CSV には厳密な規約があるわけではないので、必ずしも
連記せねばならないというルールでは無いですが、少なくとも TextFieldParser は
今回のパターンには耐えられないと思いますよ。


> 改行も含まれているので
カンマも含まれていますか?

仮に、「,」も「"」も許容するルールだとすると、
 「"AAA,BBB","CCC"」→「AAA,BBB」「CCC」
 「"AAA,BBB","CCC"」→「"AAA」「BBB"」「"CCC"」
 「"AAA,BBB","CCC"」→「AAA,BBB","CCC」
のように、いろいろな解釈が生まれてしまいますので、
まずはルールを明確にしたほうが良いと思います。


また改行も、Excel ではデータ区切りを CrLf、データ内改行を Lf とするなどといった
方言実装があるため、こちらも厳密に定義した方が良いでしょう。たとえば
改行を「データ区切り」に使うのと、「データ末尾に必ず付与」するのとでは、
ファイル末尾に改行があるかどうかが異なってきますよね。
引用返信 編集キー/
■72653 / inTopicNo.4)  Re[2]: TextFieldParserでCSVファイル取り込み
□投稿者/ シルバ (2回)-(2014/07/01(Tue) 18:06:48)
2014/07/01(Tue) 18:09:41 編集(投稿者)
2014/07/01(Tue) 18:09:37 編集(投稿者)

No72650 (魔界の仮面弁士 さん) に返信
返信ありがとうございます。

>TextFieldParser では対応できないはずです。
>面倒ですが、互換クラスを自作するなどして対応することになるかと。

> まぁ、CSV には厳密な規約があるわけではないので、必ずしも
> 連記せねばならないというルールでは無いですが、少なくとも TextFieldParser は
> 今回のパターンには耐えられないと思いますよ。
TextFieldParserだと簡単にできると思っていたので残念です。

> カンマも含まれていますか?
含まれています。

> 仮に、「,」も「"」も許容するルールだとすると、
>  「"AAA,BBB","CCC"」→「AAA,BBB」「CCC」
>  「"AAA,BBB","CCC"」→「"AAA」「BBB"」「"CCC"」
>  「"AAA,BBB","CCC"」→「AAA,BBB","CCC」
> のように、いろいろな解釈が生まれてしまいますので、
> まずはルールを明確にしたほうが良いと思います。
データは(")で囲まれているのが前提なのでルールとしては一番上の解釈になります。

> また改行も、Excel ではデータ区切りを CrLf、データ内改行を Lf とするなどといった
> 方言実装があるため、こちらも厳密に定義した方が良いでしょう。たとえば
> 改行を「データ区切り」に使うのと、「データ末尾に必ず付与」するのとでは、
> ファイル末尾に改行があるかどうかが異なってきますよね。
そうですね。
クライアントからのデータがバラバラなので、ルールを明確にするのがなかなか難しいです。

今回は時間が無いので、エラーが起こるデータもわかっているから、エラーにならないように処理をしてみます。
落ち着いたら自作で作って見ようかと思います。
ありがとうございました。
解決済み
引用返信 編集キー/
■72654 / inTopicNo.5)  Re[3]: TextFieldParserでCSVファイル取り込み
□投稿者/ 魔界の仮面弁士 (39回)-(2014/07/01(Tue) 18:29:46)
2014/07/02(Wed) 09:39:00 編集(投稿者)

No72653 (シルバ さん) に返信
>>仮に、「,」も「"」も許容するルールだとすると、
>> 「"AAA,BBB","CCC"」→「AAA,BBB」「CCC」
>> 「"AAA,BBB","CCC"」→「"AAA」「BBB"」「"CCC"」
>> 「"AAA,BBB","CCC"」→「AAA,BBB","CCC」
>>のように、いろいろな解釈が生まれてしまいますので、
>>まずはルールを明確にしたほうが良いと思います。
> データは(")で囲まれているのが前提なのでルールとしては一番上の解釈になります。
ということは、
 「"AAA,BBB",CCC","DDD"」→「AAA,BBB",CCC」「DDD」
となるのでしょうか。ルール定義が難しいですね。


> クライアントからのデータがバラバラなので、ルールを明確にするのがなかなか難しいです。
両端が囲まれている、というルールということは、
 「"AAA,BBB",CCC"」
 「"AAA,BBB,"CCC"」
などをどう扱うのかも気になりますね。
AAAからCCCまでを単一のデータとして扱うのか、
それとも CCC の部分が囲まれていないとしてエラー扱いにするのか。

# 正規表現 + LINQ あたりで、手軽に処理できないものかな…。
解決済み
引用返信 編集キー/
■72661 / inTopicNo.6)  Re[4]: TextFieldParserでCSVファイル取り込み
□投稿者/ shu (601回)-(2014/07/02(Wed) 08:21:37)
こんな感じでどうでしょう?
提示されているケースに合わないとどうなるかは分かりません。
解決済はとりあえずチェックしときます。

        Dim Values = TextBox1.Text.Split(","c)
        Dim Result As New List(Of String)
        Dim LastValue = String.Empty

        For Each Value In Values
            If Value.StartsWith("""") AndAlso LastValue.Length > 0 AndAlso LastValue.EndsWith("""") Then
                '先頭が"で前の項目が"で終わっていれば前の項目を確定
                Result.Add(LastValue)
                LastValue = Value
            Else
                'そうでなければ連結する
                If LastValue.Length > 0 Then
                    LastValue &= ","
                End If
                LastValue &= Value
            End If
        Next
        If LastValue.Length > 0 Then
            Result.Add(LastValue)
        End If

        ListBox1.DataSource = Result

解決済み
引用返信 編集キー/
■72739 / inTopicNo.7)  Re[4]: TextFieldParserでCSVファイル取り込み
□投稿者/ シルバ (3回)-(2014/07/10(Thu) 10:42:21)
2014/07/10(Thu) 10:42:37 編集(投稿者)

No72654 (魔界の仮面弁士 さん) に返信
返信が遅れてしまいすいませんでした。

>  「"AAA,BBB",CCC","DDD"」→「AAA,BBB",CCC」「DDD」
> となるのでしょうか。ルール定義が難しいですね。
実際のデータを見たらなんとなく「こう書きたいんだろうな」と想像できますが、
厳密にルールを定義すると本当に難しいです。

> 両端が囲まれている、というルールということは、
>  「"AAA,BBB",CCC"」
>  「"AAA,BBB,"CCC"」
> などをどう扱うのかも気になりますね。
> AAAからCCCまでを単一のデータとして扱うのか、
> それとも CCC の部分が囲まれていないとしてエラー扱いにするのか。
エラー扱いでいいと思います。
さすがにこんなデータが来るとどうしたいのかわかりません(笑)
色々なパターンを考えるとキリがないですね。

> # 正規表現 + LINQ あたりで、手軽に処理できないものかな…。
LINQは考えていなかったのでちょっと調べてみます。

ありがとうございました。
解決済み
引用返信 編集キー/
■72740 / inTopicNo.8)  Re[5]: TextFieldParserでCSVファイル取り込み
□投稿者/ シルバ (4回)-(2014/07/10(Thu) 10:51:54)
No72661 (shu さん) に返信
返信が遅れてすいませんでした。

> こんな感じでどうでしょう?
> 提示されているケースに合わないとどうなるかは分かりません。
> 解決済はとりあえずチェックしときます。
>
> Dim Values = TextBox1.Text.Split(","c)
> Dim Result As New List(Of String)
> Dim LastValue = String.Empty
>
> For Each Value In Values
> If Value.StartsWith("""") AndAlso LastValue.Length > 0 AndAlso LastValue.EndsWith("""") Then
> '先頭が"で前の項目が"で終わっていれば前の項目を確定
> Result.Add(LastValue)
> LastValue = Value
> Else
> 'そうでなければ連結する
> If LastValue.Length > 0 Then
> LastValue &= ","
> End If
> LastValue &= Value
> End If
> Next
> If LastValue.Length > 0 Then
> Result.Add(LastValue)
> End If
>
> ListBox1.DataSource = Result
>
試してから返事をするべきなのですが、回答に対する返事が
遅れてしまったので、まずお礼を申し上げます。
ありがとうございました。
後日、上記の方法で色々なパターンを試してみて、結果を報告します。

解決済み
引用返信 編集キー/
■72744 / inTopicNo.9)  Re[5]: TextFieldParserでCSVファイル取り込み
□投稿者/ シルバ (6回)-(2014/07/10(Thu) 17:52:03)
2014/07/10(Thu) 17:52:14 編集(投稿者)

No72661 (shu さん) に返信

提案していただいた方法を試してみました。
成功はしませんでしたが、期待した値に近い結果が得られました。
ありがとうございました。

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


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

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -