放置
すごい勢いで放置中でした。
下のコードはすでに恥ずかしいし。どうしよう。そのうち塗り替える。はず…
RFC 4180に準拠したCSVデータを読み込みたい!
もしかしたらどっか(apacheとか…)にありそうだけれども勉強ついでに。
非常に泥臭い感じに仕上がっております。全力。
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class CsvReader { private BufferedReader bufferedReader; public CsvReader(String filePath) throws IOException { bufferedReader = new BufferedReader(new InputStreamReader( new FileInputStream(filePath), System .getProperty("file.encoding"))); } public String[] readLineColumns() throws IOException { ListlineColumns = new ArrayList (); // カラム文字列 StringBuilder element = null; // クォート開始フラグ boolean isQuotBegan = false; // クォート出現カウンタ int cntQuot = 0; while (true) { // 文字コード読込み int code = bufferedReader.read(); // 現在文字コードがファイル終端の場合 if (code < 0) { if (element != null) { // 返却リストにカラム文字列を追加 lineColumns.add(element.toString()); } // レコード終了のためループ終了 break; } // クォート開始判定 if (!isQuotBegan && code == 0x22) { // RFC4180準拠であれば、クォートで開始されていないカラム内に、 // クォートが存在することはありえない isQuotBegan = true; continue; } // 文字変換 char nowChar = (char) code; if (element == null) { element = new StringBuilder(); } if (isQuotBegan) { // 要素がクォーテーションで開始されている場合 // カンマ、クォーテーション、改行が存在し // クォーテーションはクォーテーションでエスケープされている if (nowChar == 0x0d && cntQuot == 1) { // 現在文字コードが CR で、 // かつ、クォート出現済の場合 // 閉じクォートと判断し、カラム文字列確定 // 改行コード判定のため、マーク設定 bufferedReader.mark(1); // 次文字取得 char next = (char) bufferedReader.read(); if (next != 0x0a) { // 次文字が LF でない場合 // CR でレコードが終了しているとみなし、 // マーク位置(次文字取得以前)にリセット bufferedReader.reset(); } // 返却リストにカラム文字列を追加 lineColumns.add(element.toString()); // レコード終了のためループ終了 break; } else if (nowChar == 0x0a && cntQuot == 1) { // 現在文字コードが LF で、 // かつ、クォート出現済の場合 // 閉じクォートと判断し、カラム文字列確定 // 返却リストにカラム文字列を追加 lineColumns.add(element.toString()); // レコード終了のためループ終了 break; } else if (nowChar == 0x2c && cntQuot == 1) { // 現在文字コードがカンマで、 // かつ、クォート出現済の場合 // 閉じクォートと判断し、カラム文字列確定 // 返却リストにカラム文字列を追加 lineColumns.add(element.toString()); // 現状のカラム文字列削除 element.delete(0, element.length()); // クォート開始フラグ・カウンタ初期化 isQuotBegan = false; cntQuot = 0; } else if (nowChar == 0x22) { // 現在文字コードがクォートの場合 if (cntQuot == 1) { // エスケープ用のクォートが存在した場合 // 現在文字をカラム文字列に追加し、 // カウンタクリア element.append(nowChar); cntQuot = 0; } else { // カウントアップ cntQuot++; } } else { // 上記条件に当てはまらない場合 // 現在文字をカラム文字列に追加 element.append(nowChar); } } else { // 要素がクォーテーションで開始されていない場合 // 要素内にカンマ、クォーテーション、改行は存在しない if (nowChar == 0x0d) { // 現在文字コードが CR の場合 // 改行コード判定のため、マーク設定 bufferedReader.mark(1); // 次文字取得 char next = (char) bufferedReader.read(); if (next != 0x0a) { // 次文字が LF でない場合 // 改行(CR)でレコードが終了しているとみなし、 // マーク位置(次文字取得以前)にリセット bufferedReader.reset(); } // 返却リストにカラム文字列を追加 lineColumns.add(element.toString()); // レコード終了のためループ終了 break; } else if (nowChar == 0x0a) { // 現在文字コードが LF の場合 // 返却リストにカラム文字列を追加 lineColumns.add(element.toString()); // レコード終了のためループ終了 break; } else if (nowChar == 0x2c) { // 現在文字コードがカンマの場合 // 返却リストにカラム文字列を追加 lineColumns.add(element.toString()); // 現状のカラム文字列削除 element.delete(0, element.length()); } else { // 上記条件に当てはまらない場合 // 現在文字をカラム文字列に追加 element.append(nowChar); } } } if (lineColumns.isEmpty()) { return null; } return lineColumns.toArray(new String[0]); } }
たぶん大丈夫なはず…
再帰したい!と思ってましたが結局普通のループで。しかもwhile(true)…
分岐も多いし、行ったり来たりやし。なんか不満だけれども。
すぐ忘れるのでメモ代わり。すごい閃いたら塗り替えます。