- - PR -
セル内に改行コードが存在するCSVの取り込み方法
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2006-12-06 22:47
御意。元記事を読む限りは、万一「別のツール」にバグがあって連結した文字列が一定の長さを超えたり、カンマで区切ったときに列数がおかしかったらエラーに落としてかまわない・・ですね。 | ||||
|
投稿日時: 2006-12-07 09:50
分かって書いてらっしゃると思いますが、念のため。 1行に複数の改行コードが入っているケースもあるので、 連結した結果でもう一度改行コードを数えて、奇数個なら 更に次の行を連結する必要がありますね。 | ||||
|
投稿日時: 2006-12-07 10:42
るぱんです。
出てくるCSVは絶対に正しいはず! って言い切れるのであれば、力技でかわせます。
こんなアルゴリズムでどうでしょう? | ||||
|
投稿日時: 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); } } | ||||
|
投稿日時: 2006-12-07 11:19
元記事の「別のツール」の仕様次第ですが、CSVの場合は「ちょっとヘンじゃない?」と思っても無理矢理対応しないといけないことが多いので考慮しておくに越したことはないでしょうねぇ・・。 普通は(というか自分が作るなら)「Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes.」に従って作りますから、1レコードには偶数と決まるんですが(汗 [ メッセージ編集済み 編集者: shimix 編集日時 2006-12-07 11:20 ] |