Java CSVファイル読み込み

JavaCSV ファイルをスマートに読み込む方法

CSV (Comma Separated Values) ファイルは、表形式のデータを扱うための一般的なファイル形式です。JavaCSV ファイルを読み込む方法はいくつかありますが、この記事では、基本的な方法からより洗練されたライブラリの利用まで、幅広く解説します。

1. BufferedReader を使った基本的な読み込み

最も基本的な方法は、java.io.BufferedReader を利用して1行ずつ読み込み、, (カンマ) で分割する方法です。


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CSVReaderBasic {
    public static void main(String[] args) {
        String csvFilePath = "data.csv"; // 読み込む CSV ファイルのパス

        try (BufferedReader br = new BufferedReader(new FileReader(csvFilePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                // カンマで分割
                String[] fields = line.split(",");
                System.out.println(Arrays.toString(fields));

                // ここで分割されたフィールドを処理する
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ポイント:

  • BufferedReader を使うことで、効率的にファイルを1行ずつ読み込めます。
  • line.split(",") で、1行の文字列をカンマで区切って String 型の配列に変換します。
  • try-with-resources 構文を使うことで、BufferedReader のクローズ処理を自動化できます。

注意点:

  • この方法は、CSV ファイルの構造が非常に単純な場合に適しています。
  • フィールド内にカンマが含まれる場合や、ダブルクォートで囲まれたフィールドを正しく処理できません。

2. Apache Commons CSV ライブラリの利用

より複雑な CSV ファイルを扱う場合や、より柔軟な読み込み処理を行いたい場合は、Apache Commons CSV ライブラリの利用を強く推奨します。このライブラリは、RFC 4180 に準拠した CSV ファイルの読み書きをサポートしており、様々なオプションを提供しています。

2.1. 依存関係の追加

Maven を利用している場合は、pom.xml に以下の依存関係を追加します。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv<<artifactId>
    <version>1.10.0</version> </dependency>

Gradle を利用している場合は、build.gradle に以下を追加します。

implementation 'org.apache.commons:commons-csv:1.10.0' // 最新バージョンを確認してください

2.2. Apache Commons CSV を使った読み込み


import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class CSVReaderCommons {
    public static void main(String[] args) {
        String csvFilePath = "data.csv";

        try (Reader reader = new FileReader(csvFilePath)) {
            Iterable records = CSVFormat.DEFAULT.parse(reader);
            for (CSVRecord record : records) {
                // インデックスまたはヘッダー名でフィールドにアクセス
                String field1 = record.get(0);
                String field2 = record.get("ヘッダー2"); // ヘッダー行がある場合

                System.out.println("フィールド1: " + field1 + ", フィールド2: " + field2);

                // レコードのすべてのフィールドを処理する場合
                // for (String field : record) {
                //     System.out.println("フィールド: " + field);
                // }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ポイント:

  • CSVFormat.DEFAULT.parse(reader) で、CSV ファイルの内容を Iterable<CSVRecord> として取得します。
  • CSVRecord オブジェクトは、1行のデータを表します。
  • record.get(index) でインデックスを指定してフィールドにアクセスできます(0から始まる)。
  • ヘッダー行がある場合は、CSVFormat.DEFAULT.withHeader().parse(reader) を使用し、record.get("ヘッダー名") でヘッダー名を指定してフィールドにアクセスできます。

2.3. CSVFormat のカスタマイズ

CSVFormat をカスタマイズすることで、区切り文字、囲み文字、エスケープ文字、ヘッダーの有無などを細かく設定できます。


import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class CSVReaderCommonsCustom {
    public static void main(String[] args) {
        String csvFilePath = "custom_data.csv"; // 区切り文字がセミコロンのファイル

        try (Reader reader = new FileReader(csvFilePath)) {
            Iterable records = CSVFormat.newFormat(';').withHeader().parse(reader);
            for (CSVRecord record : records) {
                String field1 = record.get("名前");
                String field2 = record.get("年齢");
                System.out.println("名前: " + field1 + ", 年齢: " + field2);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

主なカスタマイズオプション:

  • .newFormat(char delimiter): 区切り文字を指定します。
  • .withQuote(char quote): 囲み文字を指定します(デフォルトは ")。
  • .withEscape(char escape): エスケープ文字を指定します。
  • .withHeader(String... header): ヘッダー行を指定します。
  • .withFirstRecordAsHeader(): 最初の行をヘッダーとして扱います。
  • .withSkipHeaderRecord(): ヘッダー行をスキップしてデータ行から読み込みを開始します。

3. OpenCSV ライブラリの利用

Apache Commons CSV と並んでよく利用されるのが、OpenCSV ライブラリです。こちらも柔軟な CSV ファイルの読み書きをサポートしています。

3.1. 依存関係の追加

Maven を利用している場合は、pom.xml に以下の依存関係を追加します。

<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>5.9</version></dependency>

Gradle を利用している場合は、build.gradle に以下を追加します。

implementation 'com.opencsv:opencsv:5.9' // 最新バージョンを確認してください

3.2. OpenCSV を使った読み込み


import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.exceptions.CsvException;

import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class CSVReaderOpenCSV {
    public static void main(String[] args) {
        String csvFilePath = "data.csv";

        try (CSVReader reader = new CSVReaderBuilder(new FileReader(csvFilePath)).build()) {
            String[] nextRecord;
            while ((nextRecord = reader.readNext()) != null) {
                System.out.println(Arrays.toString(nextRecord));
                // ここで読み込んだレコードを処理する
            }
        } catch (IOException | CsvException e) {
            e.printStackTrace();
        }
    }
}

ポイント:

  • CSVReaderBuilder を使って CSVReader オブジェクトを生成します。
  • reader.readNext() で、CSV ファイルの次の行を String 型の配列として読み込みます。
  • try-with-resources 構文は CSVReader でも利用可能です。

3.3. ヘッダー付き CSV の読み込み

ヘッダー付きの CSV ファイルを読み込む場合は、CSVReaderHeaderAware を利用できます。


import com.opencsv.CSVReaderHeaderAware;
import com.opencsv.exceptions.CsvException;

import java.io.FileReader;
import java.io.IOException;
import java.util.Map;

public class CSVReaderOpenCSVHeader {
    public static void main(String[] args) {
        String csvFilePath = "header_data.csv";

        try (CSVReaderHeaderAware reader = new CSVReaderHeaderAware(new FileReader(csvFilePath))) {
            Map nextRecord;
            while ((nextRecord = reader.readMap()) != null) {
                String name = nextRecord.get("名前");
                String age = nextRecord.get("年齢");
                System.out.println("名前: " + name + ", 年齢: " + age);
            }
        } catch (IOException | CsvException e) {
            e.printStackTrace();
        }
    }
}

ポイント:

  • CSVReaderHeaderAware を使うと、各行のデータがヘッダー名をキーとする Map として読み込まれます。

まとめ

JavaCSV ファイルを読み込む基本的な方法から、Apache Commons CSV や OpenCSV といった便利なライブラリの利用方法まで解説しました。

  • 単純な CSV ファイルの場合は、BufferedReadersplit() で十分対応できることがあります。
  • より複雑な CSV ファイルや、柔軟な読み込み処理が必要な場合は、Apache Commons CSV や OpenCSV のような専用のライブラリを利用することで、より堅牢で効率的なコードを書くことができます。

プロジェクトの要件や CSV ファイルの構造に合わせて、最適な方法を選択してください。これらの知識を活用して、Java での CSV ファイル処理をよりスマートに進めていきましょう。