- PR -

セル内に改行コードが存在するCSVの取り込み方法

投稿者投稿内容
shimix
ぬし
会議室デビュー日: 2004/08/05
投稿数: 512
お住まい・勤務地: 大分市
投稿日時: 2006-12-06 22:47
引用:

わちゃさんの書き込み (2006-12-06 20:42) より:
なんか、複雑な話になっていますが、最初に行を読むときにダブルクォートが奇数個だったら、次の行を連結すればいいのではないでしょうか?


御意。元記事を読む限りは、万一「別のツール」にバグがあって連結した文字列が一定の長さを超えたり、カンマで区切ったときに列数がおかしかったらエラーに落としてかまわない・・ですね。
kyo
会議室デビュー日: 2006/05/17
投稿数: 18
投稿日時: 2006-12-07 09:50
引用:

わちゃさんの書き込み (2006-12-06 20:42) より:
なんか、複雑な話になっていますが、最初に行を読むときにダブルクォートが奇数個だったら、次の行を連結すればいいのではないでしょうか?



分かって書いてらっしゃると思いますが、念のため。
1行に複数の改行コードが入っているケースもあるので、
連結した結果でもう一度改行コードを数えて、奇数個なら
更に次の行を連結する必要がありますね。
るぱん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 1370
投稿日時: 2006-12-07 10:42
るぱんです。

出てくるCSVは絶対に正しいはず!
って言い切れるのであれば、力技でかわせます。

コード:
改行が出てきた場合に、文字列をつなげるための文字列変数(1)を定義
期待値格納用の配列変数(2)を定義

改行でSplitし、配列に格納。以後、配列をループで回す
	文字列変数(1)に改行をコミコミで追加
	内部のカンマの数をカウントする(文字列変数(1)を加工しないことに注意が必要)
	内部のカンマが定数以下

	内部のカンマが定数どおり
		配列変数(2)に文字列変数(1)を格納
		文字列変数(1)を初期化

	内部のカンマが定数以上
		エラー処理。メッセージボックスあたりで、デバッグ




こんなアルゴリズムでどうでしょう?
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-07 11:10
aa"aa,bbb
ccc,ddd

という内容のCSVを開いてみてください。
ちゃんとパースしないで、奇数というのはだめですよ。
(という私も製品用に作ったのでないので
ちゃんとCSVの定義を調べたわけではないが)
 話がややこしくなるので、コードを書いておきます。
CSVの定義調べてバグがあったり必要なら修正してください。


/**
* 1行解析.
* 1行分の文字列を欄に区切って配列にします.
* @param line 1行文字列
* @return パース完了した場合対応する項目リストを返し、解析途中の場合null
*/
private final List parseLine(String line) throws Exception
{
if (m_items==null) {
// 解析途中でない場合の初期化
m_buf = new StringBuffer();
m_items = new Vector();
}
for (int i=0;i<line.length();i++) {
char c = line.charAt(i);
switch (m_mode) {
case 0:
switch (c) {
case '\"':
m_mode = 1;
break;

case '\r':
break;

case ',':
// 欄の区切りが見つかった
m_items.add(m_buf.toString().trim());
m_buf = new StringBuffer();
break;

default:
m_buf.append(c);
break;
}
break;

case 1: // 引用符の後
if (c=='\"') {
if ((i+1 < line.length()) && (line.charAt(i+1)=='\"')) {
// 連続する引用符は引用符文字として扱う
m_buf.append(c);
i++;
}
else {
// そうでなければ引用符終了
m_mode = 0;
}
}
else {
m_buf.append(c);
}
break;

default:
// ここにくることはありえない
throw new IllegalStateException("internal state error: m_mode=" + m_mode);
}
}
if (m_mode==0) {
m_items.add(m_buf.toString());
List retobj = m_items;
initItems();
return(retobj);
}
else {
// 解析途中で終了する場合はreadLineで含まれない改行を入れておきます
m_buf.append(LF);
return(null);
}
}

shimix
ぬし
会議室デビュー日: 2004/08/05
投稿数: 512
お住まい・勤務地: 大分市
投稿日時: 2006-12-07 11:19
引用:

だっちょさんの書き込み (2006-12-07 11:10) より:
aa"aa,bbb
ccc,ddd

という内容のCSVを開いてみてください。
ちゃんとパースしないで、奇数というのはだめですよ。


元記事の「別のツール」の仕様次第ですが、CSVの場合は「ちょっとヘンじゃない?」と思っても無理矢理対応しないといけないことが多いので考慮しておくに越したことはないでしょうねぇ・・。

普通は(というか自分が作るなら)「Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes.」に従って作りますから、1レコードには偶数と決まるんですが(汗

[ メッセージ編集済み 編集者: shimix 編集日時 2006-12-07 11:20 ]

スキルアップ/キャリアアップ(JOB@IT)