文字列として扱うCSVファイルの取り扱い方法

このQ&Aのポイント
  • CSVファイルの中で文字として扱いたい場合、カンマやダブルクォートに注意が必要です。
  • C言語ではfgetsとstrtokを使用してCSVファイルを効率的に取り扱うことができます。
  • カンマ間の項目のダブルクォート数をカウントし、その数に応じて文字列を取り扱う方法を説明しています。
回答を見る
  • ベストアンサー

文字として, "を使用するCSVファイルの取り扱い

題名の通り、文字として,(カンマ)、"(ダブルクォート)を使用するCSVファイルの取り扱いについて教えて頂きたいです。 読み込むCSVファイルの形式は以下の通りです。 ・項目の最初と最後には"が設定される ・項目内の,は文字として扱う 例:"5,000" 5の後の,は項目内に設定されている為、文字として扱う ・項目内に"を設定する場合は""と設定する ・レコードは改行コード単位 例:"A","5,000","B","C""D""" 1項目目:"A" 2項目目:"5,000" 3項目目:"B" 4項目目:"C""D""" 上記の様なCSVファイルを読み込み、項目を取得するにはC言語ではどの様に対応するべきでしょうか。 下記方法で対応出来そうですが、効率が非常に悪いと思われます。 (1)fgetsにて1行分のレコードを読み込む。 (2)取得したレコードに対して、カンマを指定してstrtokを実行し、,間の値を取得する。 (3)取得したカンマ間の項目のダブルクォートの数をカウントする。 (4)-1カウント数が偶数の場合 ,を区切り文字とし、取得した値を1項目として扱う。 (4)-2カウント数が奇数の場合 ,を文字とし、次のカンマ間の項目を取得し、連結する。 連結した値のダブルクォート数をカウントし、カウント数が奇数か偶数か判定する。 (5)上記処理をstrtok結果がNULLになるまで繰り返し、NULLが帰ってきたら次の行のレコードを読み込む。 (6)上記処理をEOFまで繰り返す。 以上、よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wap58
  • ベストアンサー率33% (29/87)
回答No.4

ざっくりstrtokで改行も弾いて関数使いまくり','に置き換えました やはり文字列飲み込んで"カウントして切り貼りしなきゃいけないかな #include <stdio.h> #include <string.h> int main(void){ char str[] = "\"100,AAA,002\",\"1,B\nB\"2B,,B3\",\"1CCC,\n,\"2\"3,4\""; char *point = str , mem[10][30] = {{}} , co_1 , co_2; for(co_1 = 0; (point = strtok(point,",\n")) != NULL; co_1++){ if(*(point+(strlen(point)-1)) != '"'){ strcat(strcat(mem[co_1],point),","); co_1--; }else{ strcat(mem[co_1],point); } point = NULL; } for(co_2 = 0; co_2 < co_1; co_2++) printf("%s\n",mem[co_2]); return 0; }

その他の回答 (3)

回答No.3

その昔、状態遷移を使って同様のCSV-parserを実装しました。

参考URL:
http://codezine.jp/article/detail/5531

参考URLに記載の質問のベストアンサーのロジックがご要望に適しているかと思います。 CSVの一般的な書式はRFC4180に定義されていますので、 ご参考までに。 http://www.kasai.fm/wiki/rfc4180jp 但し、ダブルクォート有りの場合、ダブルクォート内に改行も記述する事が可能なので、 これも考慮する必要があります。 この場合、各項目を抽出する前にダブルクォートが偶数となるまで 次行と連結する処理などが必要となります。

参考URL:
http://okwave.jp/qa/q4435021.html
daisuki1192
質問者

お礼

ありがとうございます。 区切り文字を","としている点が少し私の行いたい事と異なっていましたがロジックはかなり参考になりました。

  • maiko0333
  • ベストアンサー率19% (840/4403)
回答No.1

(1)は良いとして、 (2)から(4)は""を"に置き換えていけばいいと思います。 ロジック的に言うと「"が出てきたら1つ前が"なら無視する」でいい。

daisuki1192
質問者

お礼

ありがとうございます。 参考にさせていただきます。

関連するQ&A

  • ダブルクォートで囲まれたCSVファイルについて

    CSVを読みこんで配列変換するロジックを考えていますがうまくいきません。 ソースは以下の通りです。 Dim objFs Dim objSm Dim strLine Dim arySplit Set objFs = CreateObject("Scripting.FileSystemObject") Set objSm = objFs.OpenTextFile(C:\sample.csv, 1) Do Until objSm.AtEndOfStream strLine = objSm.ReadLine strLine = Right(strLine, Len(strLine) - 1) strLine = Left(strLine, Len(strLine) - 1) arySplit = Split(strLine, "\"\",\"\"") MsgBox UBound(arySplit) Loop Set objSm = Nothing Set objFs = Nothing ※読み込むCSVファイルはダブルクォートが付いています。 ※正常に配列に変換できたかを確認する為、MsgBoxで配列の要素数を表示しようとしています。 やりたい事は 1.まずは先頭と最後のダブルクォートを除外。 2.区切り文字(\",\")で配列に変換。  ※なぜカンマで配列に変換しないかというとダブルクォートで囲まれた値の中にカンマ文字がある為、このような事をしています。 3.変数に変換した配列を格納。 申し訳ありませんがご教授いただけませんでしょうか。 またどうか皆さんのお知恵を私にお貸しいただけませんでしょうか。 何卒、宜しくお願い致します。

  • PHP+MySQL でのcsvファイルインポート

    PHP + MySQL で、他システムから出力されてきたcsvファイルをテーブルへインポートしたいと考えています。 LOAD DATA INFILE で取り込もうとしていますが、対象のcsvファイルの特徴のためにうまく行かず苦戦しています。 取り込みたいファイルは、以下のようになっています。  ・各フィールドが "(ダブルクォート) で囲まれている  ・各フィールドは ,(カンマ) で区切られている  ・金額の項目には、桁区切りのカンマが入っている  例) "0001","あああああ",…(中略)…,"105,000","100,000","5,000",…     コード 項目名            税込み  税抜き 消費税  というような形です。    困っているのは、金額に使われている、桁区切りのカンマの処理についてです。  目的としては、データベースへ取り込むときには 105,000 は 105000 として取り込めればいいのですが、他システムから、桁区切りがなされた状態でcsvが作成されてきています。 LOAD DATA INFILE test.csv INTO TABLE data_table FIELDS TERMINATED BY ',' ENCLOSED BY '\"' IGNORE 1 LINES;  各項目のダブルクォートはENCLOSED BY で、項目を分けるカンマはTERMINATED BYで処理できていると思うのですが、金額の区切りに使われているカンマと項目の区切りのカンマを区別させられずに苦戦しています。  事前にcsvを加工するのも考えてはいるのですが、なるべくcsvを加工せずにそのまま取込したいと思います。  何か、簡単に回避できる方法等があればご教示願います。  宜しくお願いします。

    • ベストアンサー
    • PHP
  • 数値をそのまま扱ってくれるCSVエディタ

    CSV(コンマ区切りテキスト)のエディタを探しています。 条件としては、 ・データ内にコンマ(,)を使う必要があるので、各データをダブルクオート(")でくくるというオプションがある。もしくは必ずくくる設定である。 ・頭にゼロ(0)のくる数字だけのデータ(例:012)があるが、これを数値として扱うと頭のゼロが消えてしまうので、すべてのデータを文字として扱うというオプションがある。もしくは必ず文字として扱う設定である。 ということがあります。 しかし、前者はクリアできても後者に対応したものを見つけることができませんでした。良いソフトがあれば教えて下さい。

  • CでCSVファイルを扱う

    いつもお世話になっております。 今回はCSVファイルの扱いについてお聞きしたいです。 現在、 "hoge","hogehoge","…","…" というようなCSVファイルを扱いたいと思い、いろいろ試しているのですがなかなかうまくいきません。 CSVの各行をgetlineで取得して、カンマで分けるだけならできたのですが、","のまとまりで分けたいのです。現在は文字で分割はできるのですが文字列で分割する方法がわかりません。 ","で分けたい理由はたとえば"hoge,hoge"という文字列をカンマで分けてしまうと二つに分かれてしまいそれを避けたいです。 分割点の前後の文字から判断しようともしてみましたがうまくいきませんでした。 アドバイスなどありましたらご教授願います。 現在は以下のようになっております。 ifstream ifs; string temp; LPCTSTR str; ifs.open("test.csv", ios::in); while(getline(ifs, temp)) {  str = strtok(const_cast<char*>(temp.c_str()), _T(",")); printf("%s\n", str);  while(str != NULL)  {   str = strtok(NULL, ",");   if (str != NULL)   {    printf("%s\n", str);   }  } } 以上のもので CSVの"1","2","3","4" が"1"と"2"と"3"と"4"になります。 これを1と2と3と4にしたいです。 よろしくお願いします。 環境はWindowsXP VisualStudio6.0 MFC未使用 です。お願いします。

  • 文字列からダブルクオートの削除

    お世話になります、 CSVからデータを取得してDBに書き込む処理を行っているのですが、CSVデータで型が文字のものはダブルクオート(")でくくっています。 (例) "りんご",100,"円" "ばなな",200,"ドル" このままデータをStringTokenizerクラスを使用して取得した場合りんごは("りんご")のようにダブルクオートがついた状態で取得されてしまいます。 ダブルクオートを取り外す方法またはメソッドを教えていただきたいのですが、よろしくお願いします。

    • ベストアンサー
    • Java
  • CSVファイルからn個目の項目を取得する方法

    タイトルの通りCSVファイルからn個目の項目を取得する方法を教えていただきたいです。 例 1レコードあたり100項目あるCSVファイルから1個目、10個目、13個目の項目を取得する。 1レコードあたり項目数が少なければ下記コマンドでいけると思うのですが項目が多いと非常に遅くなってしまいます。 (やり方が悪いだけかもしれません) sed -e 's/¥(.*¥),¥(.*¥),•••••/¥1,¥10,¥13/' ファイル名 よろしくお願いします。

  • CSVファイルを読んでシートに書き込む方法

    エクセルのマクロ(VB6.5)でCSVファイルをよんでシートに書き込みたいのですが誰か教えて下さい。 例えば CSVファイルはこんな感じだとします。 ファイルID:test.csv ファイル内容  (1レコード)123,123,123,123,123,123  (2レコード)456,456,456,456,456  (3レコード)789,789,789,789 書き込むシートは「abcシート」とします。 CSVファイルはカンマ区切りですがレコード毎にカンマ区切りのデータ数が違います。 シートには指定したセルに書き込めば一番いいのですが、上から順番に書き込んでもいいです。 申し訳ありませんが、宜しくお願い致します。

  • ■Access エクスポート時に文字数を指定してCSV出力

    ■Access エクスポート時に文字数を指定してCSV出力 Accessのテーブルをエクスポート時に文字数を指定して、更に文字列の後ろのスペースを含めてCSV形式で出力させたいのですが可能ですか? CSVですので区切り文字は「,」(カンマ)で、全てのフィールドに対して「"」(ダブルクォート)で括りたいのです。 出力結果は下記のイメージになります。 ・1つ目のフィールドは、指定文字数「5文字」で「2文字」のスペースが含まれる ・2つ目のフィールドは、指定文字数「4文字」 ・3つ目のフィールドは、指定文字数「5文字」(2byte表記の為、10byte指定)で、「2文字」  (4byte)をスペースにする。 ---------------------------- "001 ","test","あああ  " "002 ","test","いいい  " "003 ","test","ううう  " 以上になりますが、どなたか教えていただけますでしょうか。 ACCESS初心者の為、大変申し訳ありませんが、詳しい手順もお願い致します。 宜しくお願い致します。

  • csvファイルからの読み込みがスムーズにできません

    fscanfでCSVファイルから文字列を取り込み、カンマ区切りで4つの変数に文字列を代入しようと考えているのですが、出力されたcsvファイルが変わった区切りかたをしているのでうまく変数に代入できずに困っております。 例えば、出力されたcsvファイルは以下のようになっております "ABC CO.,I","4540",""STAR"","2010/03/31" 希望としては aにABC CO.,I bに4540 cにSTAR dに2010/03/31 をそれぞれ代入したいのですが aに入る文字列にはCO.,Iというようにカンマが既にありますので カンマ区切りで読み込むとめちゃくちゃになってしまいます ですので基準をダブルクオーテーションに置き、"と"の間の文字列を代入というような形が取れれば良いのですが、このような方法での文字列取得は可能でしょうか? c言語の勉強を始めて間もない為、低レベルな質問、表現であることをお許し下さい。 よろしくお願いします。

  • CSV取込を作成しています

    文字列を取り込む際にカンマが文字列中に存在していると項目数がずれてしまうので 今回ダブルコーテーションで文字列を囲むようにプログラムの作成を考えています。 始まりのダブルコーテーションから終わりのダブルコーテーションまで一文字づつ ループで回し取得すると思われるのですが、どんな記述にすればよいかサンプルの サイトやサンプルプログラムはありますでしょうか。

    • ベストアンサー
    • Java