【Java学習|初心者向け】JavaでCSVを正しく読み込む!正規表現を活用した文字列抽出テクニック

1. 導入:なぜCSV解析に正規表現が必要なのか?

JavaでCSVファイルを扱う際、単純に「カンマで分割(split)」するだけで済ませていませんか?実は、CSVには「値の中にカンマが含まれる場合、ダブルクォーテーションで囲む」というルールがあります。これを無視してsplitメソッドを使うと、データがバラバラに壊れてしまいます。本記事では、Javaの正規表現(PatternとMatcher)を活用し、引用符を考慮した正しい抽出方法を解説します。

2. 基礎知識:CSV解析の仕組み

CSVの標準的なルール(RFC 4180)では、カンマ区切り以外に以下の要素が重要です。
ダブルクォーテーションで囲まれたフィールド:その中にあるカンマは区切り文字として扱いません。
エスケープ処理:ダブルクォーテーション自体を値として含める場合、二重(””)にして表現します。
今回は、これらを考慮した正規表現「(?<=^|,)(?:"([^"](?:""[^"]))"|([^,]))」を使用します。少し難解に見えますが、これは「先頭またはカンマの後」かつ「引用符で囲まれたグループ」または「カンマ以外の文字列」という条件を組み合わせたものです。

3. 実装と解決策

Javaではjava.util.regexパッケージのPatternクラスで正規表現をコンパイルし、Matcherクラスで文字列をスキャンします。今回は正規表現の「名前付きグループ」機能を使うことで、後からデータを取り出しやすくする工夫を取り入れます。

4. サンプルプログラム

以下のコードをコピーして、ご自身の環境で実行してみてください。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CsvParserSample {
public static void main(String[] args) {
// CSVの1行目:カンマを含むデータとダブルクォーテーションを含むデータ
String csvLine = “101,\”Tokyo, Japan\”,\”He said \”\”Hello\”\”\””;

// 正規表現の説明:
// (?:^|,) : 先頭かカンマの直後からマッチ開始
// (?:”([^”](?:””[^”]))”|([^,])) :
// – 前半:ダブルクォーテーションで囲まれたデータ(中の””はエスケープとして許可)
// – 後半:カンマ以外のデータ
String regex = “(?:^|,)(?:\”([^\”](?:\”\”[^\”]))\”|([^,]))”;

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(csvLine);

System.out.println(“— 抽出結果 —“);
while (matcher.find()) {
// グループ1は引用符あり、グループ2は引用符なしのデータ
String result = (matcher.group(1) != null) ? matcher.group(1) : matcher.group(2);

// エスケープされたダブルクォーテーションを元に戻す
result = result.replace(“\”\””, “\””);

System.out.println(“項目: ” + result);
}
}
}

5. 応用・注意点

この正規表現による手法は、小規模なデータや単一の行を処理するには非常に便利です。しかし、実務で巨大なCSVファイルを扱う場合は以下の点に注意してください。

パフォーマンスの限界:非常に巨大なファイル(数百万行など)を1行ずつ正規表現で処理すると、CPU負荷が高くなります。その場合は、Apache Commons CSVやOpenCSVといった、実績のあるサードパーティ製のライブラリを使用することを強く推奨します。
改行コードの扱い:CSVのフィールド内に「改行」が含まれている場合、上記の正規表現だけでは対応できません。その場合は、ファイル全体を読み込んで状態遷移解析を行うか、既存のライブラリに任せるのが「現場の知恵」です。

まずはこの簡易的な正規表現でCSVの構造を理解し、必要に応じてライブラリへステップアップしていきましょう。

コメント

タイトルとURLをコピーしました