1. ホーム
  2. ジャワ

JavaでCSVファイルを読み込む方法とパースする方法

2022-03-01 16:57:42
<記事
<ノスクリプト &lt;img src=&quot;http://imgconvert.csdnimg.cn/ aHR0cDovL3d3dy5ta3lvmcuY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDEzLzA0L2NvdW50cnktY3N2LWV4YW1wbGUucG5n? x-oss-process&amp;#61;image/ format,png&quot; alt=&quot;country-csv-example&quot; width=&quot;592&quot; height=&quot;206&quot; class=&quot;align center size-full wp- image-14018&quot; /&gt;

CSV(Comma Separated Values)ファイルは、データを列ごとに保存し、セパレータ(通常はカンマ "、")で区切った単なるプレーンテキストファイルである。

1,US,United States
2,MY,Malaysia
3,AU,Australia


Either

"1","US","United States"
"2","MY","Malaysia"
"3","AU","Australia"


備考
こちらをお読みください RFC4180 CSV(Comma Separated Values)形式についての文書です。

CSVファイルでは、通常、2つの問題があります。

1. セパレータを含むフィールド、例えばセパレータがカンマのフィールド。

"aaa","b,bb","ccc"


2. ダブルクォートを使ってフィールドを囲むと、フィールドにダブルクォートが含まれる。この問題を解決するには、二重引用符をフィールドの内部に表示するには、その前に別の二重引用符 ( RFC4180 )

"aaa","b""bb","ccc"


このチュートリアルでは、CSVファイルから値を読み取り、パースし、印刷するための3つの例を紹介します。

  1. CSV ファイルを簡単なフォーマットでパースするソリューションです。
  2. おかしな書式のCSVファイル(区切り文字や二重引用符を含むフィールド)を解析するための高度なソリューション
  3. サードパーティ製ソリューション、OpenCSVの例です。

1. シンプルな解決策

CSVファイルにセパレータや二重引用符が含まれていないことが確認された場合、単純に標準の split() を使用してCSVファイルをパースします。

1.1 簡単なCSVファイルの表示

/Users/mkyong/csv/country.csv
"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia"
"1.0.1.0","1.0.3.255","16777472","16778239","CN","China"
"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"
"1.0.8.0","1.0.15.255","16779264","16781311","CN","China"
"1.0.16.0","1.0.31.255","16781312","16785407","JP","Japan"
"1.0.32.0","1.0.63.255","16785408","16793599","CN","China"
"1.0.64.0","1.0.127.255","16793600","16809983","JP","Japan"
"1.0.128.0","1.0.255.255","16809984","16842751","TH","Thailand"

1.2には魔法はありません。上のテキストファイルを読み込んで、カンマ区切りで分割するだけです。

CSVReader.csv
package com.mkyong.csv;

import java.io;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io;

public class CSVReader {

    public static void main(String[] args) {

        String csvFile = "/Users/mkyong/csv/country.csv";
        BufferedReader br = null;
        String line = "";
        String cvsSplitBy = ",";

        try {

            br = new BufferedReader(new FileReader(csvFile));
            while ((line = br.readLine()) ! = null) {

                // use comma as separator
                String[] country = line.split(cvsSplitBy);

                System.out.println("Country [code= " + country[4] + " , name=" + country[5] + "]");

            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br ! = null) { try {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}

1.3 JDK 7 以降では try-resources を使用します。

CSVReader.csv
package com.mkyong.csv;

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

public class CSVReader {

    public static void main(String[] args) {

        String csvFile = "/Users/mkyong/csv/country.csv";
        String line = "";
        String cvsSplitBy = ",";

        try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {

            while ((line = br.readLine()) ! = null) {

                // use comma as separator
                String[] country = line.split(cvsSplitBy);

                System.out.println("Country [code= " + country[4] + " , name=" + country[5] + "]");

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}


出力

Country [code= "AU" , name="Australia"]
Country [code= "CN" , name="China"]
Country [code= "AU" , name="Australia"]
Country [code= "CN" , name="China"]
Country [code= "JP" , name="Japan"]
Country [code= "CN" , name="China"]
Country [code= "JP" , name="Japan"]
Country [code= "TH" , name="Thailand"]


2. 事前に解決しておく

このソリューションは、"デリミタまたはダブルクォート"を含むフィールドを解決し、カスタムデリミタとカスタム囲みフィールドもサポートします。以下のCSVパース例とJUnitテストケースで、その動作を確認してください。

<ブロッククオート

備考
同様に、フィールドに二重引用符を表示する必要があり、その前にエスケープのために別の二重引用符を付ける場合、例えば次のようになります。

"aaa","b""bb","ccc"


2.1 別のCSVファイルを表示する

/Users/mkyong/csv/country2.csv
10,AU,Australia
11,AU,Aus""tralia
"12","AU","Australia"
"13","AU","Aus","tralia"
"14","AU","Aus,tralia"

2.2 次の例は、この記事â"からヒントを得たものです。 CSVファイルのクラスだけが必要です "(一部は他の機能をサポートするために修正されているので、"修正コメント"を読んでください)と、このサードパーティの オープンCSV ライブラリです。

CSVUtils.java
package com.mkyong.utils;

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

public class CSVUtils {

    private static final char DEFAULT_SEPARATOR = ',';
    private static final char DEFAULT_QUOTE = '"';

    public static void main(String[] args) throws Exception {

        String csvFile = "/Users/mkyong/csv/country2.csv";

        Scanner scanner = new Scanner(new File(csvFile));
        while (scanner.hasNext()) {
            List<String> line = parseLine(scanner.nextLine());
            System.out.println("Country [id= " + line.get(0) + ", code= " + line.get(1) + " , name=" + line.get(2) + "]" );
        }
        scanner.close();

    }

    public static List<String> parseLine(String cvsLine) {
        return parseLine(cvsLine, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
    }

    public static List<String> parseLine(String cvsLine, char separators) {
        return parseLine(cvsLine, separators, DEFAULT_QUOTE);
    }

    public static List<String> parseLine(String cvsLine, char separators, char customQuote) {

        List<String> result = new ArrayList<>();

        //if empty, return!
        if (cvsLine == null && cvsLine.isEmpty()) {
            return result;
        }

        if (customQuote == ' ') {
            customQuote = DEFAULT_QUOTE;
        }

        if (separators == ' ') {
            separators = DEFAULT_SEPARATOR;
        }

        StringBuffer curVal = new StringBuffer();
        boolean inQuotes = false;
        boolean startCollectChar = false;
        boolean doubleQuotesInColumn = false;

        char[] chars = cvsLine.toCharArray();

        for (char ch : chars) {

            if (inQuotes) {
                startCollectChar = true;
                if (ch == customQuote) {
                    inQuotes = false;
                    doubleQuotesInColumn = false;
                } else {

                    //Fixed : allow "" in custom quote enclosed
                    if (ch == '\"') {
                        if (!doubleQuotesInColumn) {
                            curVal.append(ch);
                            doubleQuotesInColumn = true;
                        }
                    } else {
                        curVal.append(ch);
                    }

                }
            } else {
                if (ch == customQuote) {

                    inQuotes = true;

                    //Fixed : allow "" in empty quote enclosed
                    if (chars[0] ! = '"' && customQuote == '\"') {
                        curVal.append('"');
                    }

                    //double quotes in column will hit this!
                    if (startCollectChar) {
                        curVal.append('"');
                    }

                } else if (ch == separators) {

                    result.add(curVal.toString());

                    curVal = new StringBuffer();
                    startCollectChar = false;

                } else if (ch == '\r') {
                    //ignore LF characters
                    continue;
                } else if (ch == '\n') {
                    //the end, break!
                    break;
                } else {
                    curVal.append(ch);
                }
            }

        }

        result.add(curVal.toString());

        return result;
    }

}


出力

Country [id= 10, code= AU , name=Australia]
Country [id= 11, code= AU , name=Aus"tralia]
Country [id= 12, code= AU , name=Australia]
Country [id= 13, code= AU , name=Aus"tralia]
Country [id= 14, code= AU , name=Aus,tralia]


3.3 次のユニットテストを確認し、quot;カンマと二重引用符の問題をテストしなさい。

CSVUtilsTest.java
package com.mkyong.csv;

import com.mkyong.utils.CSVUtils;
import org.hamcrest.core.IsNull;
import org.junit.Test;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class CSVUtilsTest {

    @Test
    public void test_no_quote() {

        String line = "10,AU,Australia";
        List<String> result = CSVUtils.parseLine(line);

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Australia"));

    }

    @Test
    public void test_no_quote_but_double_quotes_in_column() throws Exception {

        String line = "10,AU,Aus\"\"\"tralia";

        List<String> result = CSVUtils.parseLine(line);
        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus\"tralia"));

    }

    @Test
    public void test_double_quotes() {

        String line = "\"10\",\"AU\",\"Australia\"";
        List<String> result = CSVUtils.parseLine(line);

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Australia"));

    }

    @Test
    public void test_double_quotes_but_double_quotes_in_column() {

        String line = "\"10\",\"AU\",\"Aus\"\"tralia\"";
        List<String> result = CSVUtils.parseLine(line);

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus\"tralia"));

    }

    @Test
    public void test_double_quotes_but_comma_in_column() {

        String line = "\"10\",\"AU\",\"Aus,tralia\"";
        List<String> result = CSVUtils.parseLine(line);

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus,tralia"));

    }

}

3.4 カスタムセパレータとカスタムクロージャフィールドをテストする、別のユニットテストをレビューしてください。

CSVUtilsTestCustom.java
package com.mkyong.csv;

import com.mkyong.utils.CSVUtils;
import org.hamcrest.core.IsNull;
import org.junit.Test;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class CSVUtilsTestCustom {

    @Test
    public void test_custom_separator() {

        String line = "10|AU|Australia";
        List<String> result = CSVUtils.parseLine(line, '|');

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Australia"));

    }

    @Test
    public void test_custom_separator_and_quote() {

        String line = "'10'|'AU'|'Australia'";
        List<String> result = CSVUtils.parseLine(line, '|', '\'');

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Australia"));

    }

    @Test
    public void test_custom_separator_and_quote_but_custom_quote_in_column() {

        String line = "'10'|'AU'|'Aus|tralia'";
        List<String> result = CSVUtils.parseLine(line, '|', '\'');

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus|tralia"));

    }

    @Test
    public void test_custom_separator_and_quote_but_double_quotes_in_column() {

        String line = "'10'|'AU'|'Aus\"\"\"tralia'";
        List<String> result = CSVUtils.parseLine(line, '|', '\'');

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus\"tralia"));

    }

}


3. OpenCSVの例

上記のシンプルで高度な解決策に満足できない場合は、サードパーティのCSVライブラリを使ってみてください -。 オープンCSV .

3.1 Maven

pom.xml
<dependency>
		<groupId>com.opencsv</groupId>
		<artifactId>opencsv</artifactId>
		<version>3.8</version>
	</dependency>

3.2 CSVファイルを表示する。

/Users/mkyong/csv/country3.csv
10,AU,Australia
11,AU,Aus""tralia
"12","AU","Australia"
"13","AU","Aus","tralia"
"14","AU","Aus,tralia"

3.2 OpenCSVのサンプルを使って、上記のCSVファイルをパースしてください。

CSVReaderExample.java
package com.mkyong.csv;

import com.opencsv.CSVReader;

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

public class CSVReaderExample {

    public static void main(String[] args) {

        String csvFile = "/Users/mkyong/csv/country3.csv";

        CSVReader reader = null;
        try {
            reader = new CSVReader(new FileReader(csvFile));
            String[] line;
            while ((line = reader.readNext()) ! = null) {
                System.out.println("Country [id= " + line[0] + ", code= " + line[1] + " , name=" + line[2] + "]");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

}

出力量

Country [id= 10, code= AU , name=Australia]
Country [id= 11, code= AU , name=Aus"tralia]
Country [id= 12, code= AU , name=Australia]
Country [id= 13, code= AU , name=Aus"tralia]
Country [id= 14, code= AU , name=Aus,tralia]


備考
その他の例については、こちらをご参照ください。 OpenCSVの公式ドキュメント .

完了

参考

  1. CSV ファイルにのみ必要なクラス
  2. CSVHelperの使用例
  3. Ostermiller Javaユーティリティ - カンマ区切り値(CSV)
  4. RFC4180 - カンマ区切り値(CSV)形式
  5. OpenCSVウェブサイト
  6. Java - データをCSVファイルにエクスポートする方法
タグ CSV ジャワ
<入力

Translated from : https://mkyong.com/java/how-to-read-and-parse-csv-file-in-java/