CSV形式の正式な標準はありませんが、最初にあなたが引用した醜い列に注意してください:
"abc, defghijk. "Lmnopqrs, "tuv,"" wxyz.",
CSVの基本ルールと見なされるものに準拠していません。
問題の列がルール 1) に従う場合、ルール 2) には従いません。しかし、ルール 1) に従うようにそれを解釈することができます。つまり、どこで終わるかを言うことができます。
[abc, defghijk. [Lmnopqrs, ]tuv,[] wxyz.],
バランスの取れた最も外側の引用符で列を囲みます。バランスの取れた内部クオートは、バランシングがそれらを内部にすることを除いて、内部であることの他の兆候を欠いている可能性があります.
このテキストをルール 1) と一貫して 1 つの列として解析し、ルール 2) にも従う列も解析する
ルールが必要です。両方のルールに従う列は必然的にバランス調整も可能になるため、先ほど示したバランス調整は、これが可能であることを示唆しています。
推奨されるルールは次のとおりです。
- 列は、0 個の二重引用符が先行するか、偶数個の二重引用符の最後のカンマが先行する最初のコンマまで実行されます。
コンマまでの二重引用符が偶数個ある場合、少なくとも 1 つの方法で、引用符を囲み、残りの部分のバランスを取ることができることがわかります。
あなたが検討しているより単純なルール:
引用に出くわした後、「、」が見つかるまで、引用されたジャンクを1文字ずつ読む必要がありますか?
ルール 2) に従う特定の列に一致すると失敗します。
「スーパー、「豪華」」、トラック」、
より単純なルールは、 の後に列を終了します""luxurious""
。ただし、この列はルール 2) に準拠しているため、隣接する二重引用符は「エスケープされた」二重引用符であり、区切りの意味はありません。一方、提案されたルールは引き続き列を正しく解析し、 の後に終了しtruck"
ます。
get_csv_column
関数が提案されたルールによって列を解析するデモ プログラムを次に示します。
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
/*
Assume `in` is positioned at start of column.
Accumulates chars from `in` as long as `in` is good
until either:-
- Have consumed a comma preceded by 0 quotes,or
- Have consumed a comma immediately preceded by
the last of an even number of quotes.
*/
std::string get_csv_column(ifstream & in)
{
std::string col;
unsigned quotes = 0;
char prev = 0;
bool finis = false;
for (int ch; !finis && (ch = in.get()) != EOF; ) {
switch(ch) {
case '"':
++quotes;
break;
case ',':
if (quotes == 0 || (prev == '"' && (quotes & 1) == 0)) {
finis = true;
}
break;
default:;
}
col += prev = ch;
}
return col;
}
int main()
{
ifstream in("csv.txt");
if (!in) {
cout << "Open error :(" << endl;
exit(EXIT_FAILURE);
}
for (std::string col; in; ) {
col = get_csv_column(in),
cout << "<[" << col << "]>" << std::endl;
}
if (!in && !in.eof()) {
cout << "Read error :(" << endl;
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
各列を で囲み<[...]>
、改行を無視せず、各列に終端の ',' を含めます。
ファイルcsv.txt
は次のとおりです。
...,"abc, defghijk. "Lmnopqrs, "tuv,"" wxyz.",...,
",","",
Year,Make,Model,Description,Price,
1997,Ford,E350,"Super, ""luxurious"", truck",
1997,Ford,E350,"Super, ""luxurious"" truck",
1997,Ford,E350,"ac, abs, moon",3000.00,
1999,Chevy,"Venture ""Extended Edition""","",4900.00,
1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00,
1996,Jeep,Grand Cherokee,"MUST SELL!
air, moon roof, loaded",4799.00,
出力は次のとおりです。
<[...,]>
<["abc, defghijk. "Lmnopqrs, "tuv,"" wxyz.",]>
<[...,]>
<[
",",]>
<["",]>
<[
Year,]>
<[Make,]>
<[Model,]>
<[Description,]>
<[Price,]>
<[
1997,]>
<[Ford,]>
<[E350,]>
<["Super, ""luxurious"", truck",]>
<[
1997,]>
<[Ford,]>
<[E350,]>
<["Super, ""luxurious"" truck",]>
<[
1997,]>
<[Ford,]>
<[E350,]>
<["ac, abs, moon",]>
<[3000.00,]>
<[
1999,]>
<[Chevy,]>
<["Venture ""Extended Edition""",]>
<["",]>
<[4900.00,]>
<[
1999,]>
<[Chevy,]>
<["Venture ""Extended Edition, Very Large""",]>
<[,]>
<[5000.00,]>
<[
1996,]>
<[Jeep,]>
<[Grand Cherokee,]>
<["MUST SELL!
air, moon roof, loaded",]>
<[4799.00]>