CSV ファイルの読み込み

JavaBeginner
オンラインで実践に進む

はじめに

この実験(Lab)では、Java で CSV(Comma-Separated Values、カンマ区切り値)ファイルを読み込む方法を学びます。CSV は、スプレッドシートやデータベースのエクスポートなど、表形式のデータを保存するために使用される一般的なファイル形式です。CSV ファイルの各行はデータの行を表し、列はカンマで区切られています。

Java で CSV ファイルを読み込むための 3 つの異なるアプローチを検討します。

  • java.ioパッケージのBufferedReaderクラスを使用する
  • java.utilパッケージのScannerクラスを使用する
  • CSV 処理のための人気のあるサードパーティライブラリである OpenCSV ライブラリを使用する

この実験(Lab)の終わりには、特定の要件に基づいて、Java アプリケーションで CSV ファイルを読み込むための最も適切な方法を選択できるようになります。

サンプル CSV ファイルとプロジェクト構造の作成

CSV ファイルを読み始める前に、プロジェクトが適切に設定されていることを確認しましょう。このステップでは、CSV ファイルの構造を調べ、メインの Java クラスを作成します。

CSV ファイルについて

CSV(Comma-Separated Values、カンマ区切り値)ファイルは、表形式のデータをプレーンテキストで保存します。各行は 1 つの行を表し、列はカンマで区切られています。CSV ファイルは、Excel、Google Sheets、データベースシステムなど、多くのアプリケーションとの互換性とシンプルさから、データ交換に広く使用されています。

サンプル CSV ファイルの確認

この実験(Lab)環境には、すでに~/project/sample.csvにサンプル CSV ファイルが含まれています。まず、その内容を見てみましょう。

cat ~/project/sample.csv

次のような出力が表示されるはずです。

name,age,city
John,25,New York
Alice,30,Los Angeles
Bob,28,Chicago
Eve,22,Boston

この CSV ファイルには、人々の名前、年齢、都市に関する情報を含む 4 行のデータ(ヘッダー行を含む)が含まれています。

Java クラスの作成

次に、この実験(Lab)全体で使用するsrcディレクトリに、CSVReaderDemo.javaという名前の新しい Java クラスを作成しましょう。

VSCode で、サイドバーの Explorer アイコンをクリックし、~/project/srcディレクトリに移動し、右クリックして「New File」を選択します。ファイル名をCSVReaderDemo.javaとします。

ファイルに次の基本的な構造を追加します。

public class CSVReaderDemo {
    public static void main(String[] args) {
        System.out.println("CSV Reader Demo");

        // We will add CSV reading code here in the next steps
    }
}
Create Java File

すべてが正しく設定されていることを確認するために、Java クラスをコンパイルして実行しましょう。

cd ~/project
javac -d . src/CSVReaderDemo.java
java CSVReaderDemo

次のような出力が表示されるはずです。

CSV Reader Demo

素晴らしい!これでプロジェクト構造の準備ができました。次のステップでは、CSV ファイルを読み込むためのさまざまなメソッドを実装します。

BufferedReader を使用した CSV ファイルの読み込み

このステップでは、java.ioパッケージのBufferedReaderクラスを使用して CSV ファイルを読み込む最初の方法を実装します。これは、Java でテキストファイルを読み込むための一般的で簡単な方法です。

BufferedReader について

BufferedReaderは、文字入力ストリームからテキストを読み込み、文字をバッファリングして、文字、配列、および行を効率的に読み込むクラスです。バッファサイズを指定することも、デフォルトサイズを使用することもできます。

BufferedReader を使用した CSV 読み込みの実装

CSVReaderDemo.javaファイルを更新して、BufferedReader を使用して CSV ファイルを読み込みましょう。ファイルのすべての内容を次のコードに置き換えます。

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 CSVReaderDemo {
    public static void main(String[] args) {
        System.out.println("Reading CSV using BufferedReader");

        // Path to our CSV file
        String csvFile = "sample.csv";

        // Lists to store our data
        List<List<String>> data = new ArrayList<>();

        // Try-with-resources to ensure the reader gets closed automatically
        try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
            String line;

            // Read each line from the file
            while ((line = br.readLine()) != null) {
                // Split the line by comma and convert to a List
                String[] values = line.split(",");
                List<String> lineData = Arrays.asList(values);

                // Add the line data to our main list
                data.add(lineData);
            }

            // Print the data we read
            System.out.println("\nData read from CSV file:");
            for (int i = 0; i < data.size(); i++) {
                List<String> row = data.get(i);
                System.out.println("Row " + i + ": " + String.join(", ", row));
            }

        } catch (IOException e) {
            System.err.println("Error reading the CSV file: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
Update Java File

更新されたコードをコンパイルして実行しましょう。

cd ~/project
javac -d . src/CSVReaderDemo.java
java CSVReaderDemo

次のような出力が表示されるはずです。

Reading CSV using BufferedReader

Data read from CSV file:
Row 0: name, age, city
Row 1: John, 25, New York
Row 2: Alice, 30, Los Angeles
Row 3: Bob, 28, Chicago
Row 4: Eve, 22, Boston

コードの説明

  1. ファイル I/O 操作とデータ構造に必要な Java クラスをインポートします。
  2. CSV ファイルへのパス(sample.csv)を定義します。
  3. CSV データを 2 次元リストとして格納するために、List<List<String>>を作成します。
  4. 使用後にBufferedReaderを自動的に閉じるために、try-with-resources ブロックを使用します。
  5. br.readLine()を使用して、ファイルから各行を読み込みます。
  6. 各行について、line.split(",")を使用してカンマで分割し、Listに変換します。
  7. 各行をデータのメインリストに追加します。
  8. 最後に、データを正しく読み込んだことを確認するために、データを印刷します。

BufferedReaderアプローチは、CSV ファイルを含むテキストファイルを読み込むためにシンプルで効率的です。ただし、引用符で囲まれたカンマや改行を含むフィールドなど、より複雑な CSV フォーマットを扱う場合には制限があります。

次のステップでは、Scannerクラスを使用した別の方法を検討します。

Scanner を使用した CSV ファイルの読み込み

このステップでは、java.utilパッケージのScannerクラスを使用して CSV ファイルを読み込む 2 番目の方法を実装します。Scanner クラスは、さまざまなソースからフォーマットされた入力を読み込むための便利な方法を提供します。

Scanner について

Scannerクラスは、区切り文字パターンを使用して入力をトークンに分割します。デフォルトでは、これは空白に一致します。次に、さまざまなnextメソッドを使用して、結果のトークンをさまざまな型の値に変換できます。

Scanner を使用した CSV 読み込みの実装

CSVReaderDemo.javaファイルを更新して、Scanner を使用して CSV ファイルを読み込みましょう。ファイルのすべての内容を次のコードに置き換えます。

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class CSVReaderDemo {
    public static void main(String[] args) {
        System.out.println("Reading CSV using Scanner");

        // Path to our CSV file
        String csvFile = "sample.csv";

        // Lists to store our data
        List<List<String>> data = new ArrayList<>();

        try (Scanner scanner = new Scanner(new File(csvFile))) {
            // Read each line from the file
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();

                // Split the line by comma and convert to a List
                String[] values = line.split(",");
                List<String> lineData = Arrays.asList(values);

                // Add the line data to our main list
                data.add(lineData);
            }

            // Print the data we read
            System.out.println("\nData read from CSV file:");
            for (int i = 0; i < data.size(); i++) {
                List<String> row = data.get(i);
                System.out.println("Row " + i + ": " + String.join(", ", row));
            }

        } catch (FileNotFoundException e) {
            System.err.println("CSV file not found: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

更新されたコードをコンパイルして実行しましょう。

cd ~/project
javac -d . src/CSVReaderDemo.java
java CSVReaderDemo

次のような出力が表示されるはずです。

Reading CSV using Scanner

Data read from CSV file:
Row 0: name, age, city
Row 1: John, 25, New York
Row 2: Alice, 30, Los Angeles
Row 3: Bob, 28, Chicago
Row 4: Eve, 22, Boston

コードの説明

  1. ファイル操作、Scanner、およびデータ構造に必要な Java クラスをインポートします。
  2. CSV ファイルへのパス(sample.csv)を定義します。
  3. CSV データを 2 次元リストとして格納するために、List<List<String>>を作成します。
  4. 使用後にScannerを自動的に閉じるために、try-with-resources ブロックを使用します。
  5. scanner.hasNextLine()が true を返す限り、scanner.nextLine()を使用してファイルから各行を読み込みます。
  6. 各行について、line.split(",")を使用してカンマで分割し、Listに変換します。
  7. 各行をデータのメインリストに追加します。
  8. 最後に、データを正しく読み込んだことを確認するために、データを印刷します。

Scannerアプローチは、BufferedReaderアプローチと似ていますが、さまざまな種類のデータを解析するためのより便利なメソッドを提供します。ただし、BufferedReaderと同様に、複雑な CSV フォーマットを扱う場合には制限があります。

次のステップでは、より複雑な CSV フォーマットをより効果的に処理する OpenCSV ライブラリを使用した、より堅牢なアプローチを検討します。

OpenCSV ライブラリを使用した CSV ファイルの読み込み

このステップでは、OpenCSV ライブラリを使用して CSV ファイルを読み込む 3 番目の方法を実装します。OpenCSV は、引用符で囲まれたカンマや改行を含むフィールドなど、複雑なシナリオを処理する、堅牢な CSV 解析機能を提供するサードパーティライブラリです。

OpenCSV について

OpenCSV は、すべての基本的な CSV 形式のバリエーションをサポートする、Java 用の CSV パーサーライブラリです。これまでの方法とは異なり、OpenCSV は、カンマ、改行、およびその他の特殊文字を含む引用符で囲まれたフィールドを適切に処理します。これらの文字は、そうでない場合は、カンマによる単純な分割を壊してしまいます。

OpenCSV の設定

まず、OpenCSV ライブラリとその依存関係をダウンロードしましょう。

cd ~/project
mkdir -p lib
curl -L -o lib/opencsv-5.7.1.jar https://repo1.maven.org/maven2/com/opencsv/opencsv/5.7.1/opencsv-5.7.1.jar
curl -L -o lib/commons-lang3-3.12.0.jar https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar
curl -L -o lib/commons-text-1.10.0.jar https://repo1.maven.org/maven2/org/apache/commons/commons-text/1.10.0/commons-text-1.10.0.jar
curl -L -o lib/commons-beanutils-1.9.4.jar https://repo1.maven.org/maven2/commons-beanutils/commons-beanutils/1.9.4/commons-beanutils-1.9.4.jar
curl -L -o lib/commons-collections-3.2.2.jar https://repo1.maven.org/maven2/commons-collections/commons-collections/3.2.2/commons-collections/3.2.2.jar
curl -L -o lib/commons-logging-1.2.jar https://repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar

より複雑な CSV ファイルの作成

カンマを含む引用符で囲まれたフィールドを含む、より複雑な CSV ファイルを作成しましょう。

echo 'name,description,price
"Laptop","High-performance laptop, with SSD",999.99
"Smartphone","Latest model, with dual camera",499.99
"Headphones","Noise-canceling, wireless",149.99' > ~/project/products.csv

OpenCSV を使用した CSV 読み込みの実装

次に、CSVReaderDemo.javaファイルを更新して、OpenCSV を使用して CSV ファイルを読み込みましょう。ファイルのすべての内容を次のコードに置き換えます。

import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;
import java.io.FileReader;
import java.io.IOException;

public class CSVReaderDemo {
    public static void main(String[] args) {
        System.out.println("Reading CSV using OpenCSV");

        // Path to our CSV file with complex data
        String csvFile = "products.csv";

        try (CSVReader reader = new CSVReader(new FileReader(csvFile))) {
            // Read and print the header
            String[] header = reader.readNext();
            if (header != null) {
                System.out.println("\nHeader: " + String.join(", ", header));
            }

            // Read and print each line
            String[] nextLine;
            int rowNumber = 1;

            System.out.println("\nData read from CSV file:");
            while ((nextLine = reader.readNext()) != null) {
                System.out.println("Row " + rowNumber + ":");
                for (int i = 0; i < nextLine.length; i++) {
                    System.out.println("  " + header[i] + ": " + nextLine[i]);
                }
                rowNumber++;
                System.out.println();
            }

        } catch (IOException | CsvValidationException e) {
            System.err.println("Error reading the CSV file: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

更新されたコードをコンパイルして実行しましょう。

cd ~/project
javac -cp ".:lib/*" -d . src/CSVReaderDemo.java
java -cp ".:lib/*" CSVReaderDemo

次のような出力が表示されるはずです。

Reading CSV using OpenCSV

Header: name, description, price

Data read from CSV file:
Row 1:
  name: Laptop
  description: High-performance laptop, with SSD
  price: 999.99

Row 2:
  name: Smartphone
  description: Latest model, with dual camera
  price: 499.99

Row 3:
  name: Headphones
  description: Noise-canceling, wireless
  price: 149.99

コードの説明

  1. OpenCSV ライブラリと Java I/O から必要なクラスをインポートします。
  2. CSV ファイルへのパス(products.csv)を定義します。
  3. CSV ファイルを読み込むために、CSVReaderオブジェクトを作成します。
  4. reader.readNext()を使用してヘッダー行を読み込み、後で使用するために保存します。
  5. 次に、reader.readNext()を使用して、行がなくなるまでループで各行を読み込みます。
  6. 各行について、対応するヘッダーとともに各フィールドを印刷します。

OpenCSV ライブラリは、引用符で囲まれたカンマを含むフィールドを正しく解析し、複雑な CSV フォーマットを自動的に処理します。これにより、複雑なデータを含む可能性のある実際の CSV ファイルに最適です。

OpenCSV の利点

OpenCSV は、基本的な方法よりもいくつかの利点を提供します。

  1. カンマ、改行、およびその他の特殊文字を含む引用符で囲まれたフィールドを正しく処理します。
  2. Bean(Java オブジェクト)への読み込みの組み込みサポートを提供します。
  3. カスタム区切り文字、引用符文字、およびエスケープ文字などの高度な機能をサポートしています。
  4. 大規模な CSV ファイルを効率的に処理します。

CSV ファイルを扱うほとんどの実際のアプリケーションでは、OpenCSV のような専用ライブラリを使用することが推奨されるアプローチです。

まとめ

この実験では、Java で CSV ファイルを読み込むための 3 つの異なるアプローチを検討しました。

  1. BufferedReader の使用: 標準の Java I/O ライブラリを使用したシンプルなアプローチです。基本的な CSV ファイルには適していますが、複雑な CSV フォーマットを扱う場合には制限があります。
  2. Scanner の使用: 標準の Java ユーティリティライブラリを使用した別のアプローチです。BufferedReader と同様に、シンプルな CSV ファイルに適していますが、複雑な CSV フォーマットのサポートがありません。
  3. OpenCSV の使用: CSV 処理専用に設計されたサードパーティライブラリを使用した堅牢なアプローチです。カンマ、改行、およびその他の特殊文字を含む引用符で囲まれたフィールドなど、複雑な CSV フォーマットを処理します。

各アプローチには、それぞれの強みとユースケースがあります。

  • BufferedReaderScannerは、外部の依存関係を避けたい場合に、シンプルな CSV ファイルに適しています。
  • OpenCSVは、潜在的に複雑な CSV ファイルを扱う実際のアプリケーションに最適な選択肢です。

これらの異なるアプローチを理解することで、特定の要件と CSV データの複雑さに基づいて、最も適切な方法を選択できます。

CSV ファイルは、データ処理、データ交換、およびデータ統合のシナリオで広く使用されています。CSV ファイルを読み込んで処理する能力は、Java 開発者にとって、特にデータ中心のアプリケーションや他のシステムとの統合において、貴重なスキルです。