Read / Write CSV files in Java using Apache Commons CSV

Reading or writing a CSV file is a very common use-case that Java developers encounter in their day-to-day work.

If you need a simple way to read a CSV file or generate a new one for your project then this blog post is for you.

In this post, You’ll learn how to read and write CSV files in Java using a very simple open source library called Apache Commons CSV.

Adding Apache Commons CSV dependency

First of all, you need to add apache-commons-csv dependency in your project. If you use maven, then add the following dependency to your pom.xml file -

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

If Gradle is the build system of your choice, then add the following to your build.gradle file -

compile "org.apache.commons:commons-csv:1.5"

Sample CSV file

Following is the sample CSV file that we will read and parse in our examples. It contains Name, Email, PhoneNo, and Country of Users of an application. Let’s call it users.csv.

Rajeev Kumar Singh ♥,rajeevs@example.com,+91-9999999999,India
Sachin Tendulkar,sachin@example.com,+91-9999999998,India
Barak Obama,barak.obama@example.com,+1-1111111111,United States
Donald Trump,donald.trump@example.com,+1-2222222222,United States

Sample CSV file with Header

It’s generally not a good idea to use CSV files without a header. Following is another Sample CSV file that contains a header. Let’s call it users-with-header.csv.

Name,Email,Phone,Country
Rajeev Kumar Singh ♥,rajeevs@example.com,+91-9999999999,India
Sachin Tendulkar,sachin@example.com,+91-9999999998,India
Barak Obama,barak.obama@example.com,+1-1111111111,United States
Donald Trump,donald.trump@example.com,+1-2222222222,United States

In this article, I’ll explain how to read and parse CSV files with a header and without a header using Apache Commons CSV.

The first two examples show how to read a CSV file without a header, and the third example shows how to read a CSV file with a header.

Reading a CSV file (Access Values by Column Index)

The example below shows how you can read and parse the sample CSV file users.csv described above using Apache Commons CSV -

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;

public class BasicCSVReader {
    private static final String SAMPLE_CSV_FILE_PATH = "./users.csv";

    public static void main(String[] args) throws IOException {
        try (
            Reader reader = Files.newBufferedReader(Paths.get(SAMPLE_CSV_FILE_PATH));
            CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT);
        ) {
            for (CSVRecord csvRecord : csvParser) {
                // Accessing Values by Column Index
                String name = csvRecord.get(0);
                String email = csvRecord.get(1);
                String phone = csvRecord.get(2);
                String country = csvRecord.get(3);

                System.out.println("Record No - " + csvRecord.getRecordNumber());
                System.out.println("---------------");
                System.out.println("Name : " + name);
                System.out.println("Email : " + email);
                System.out.println("Phone : " + phone);
                System.out.println("Country : " + country);
                System.out.println("---------------\n\n");
            }
        }
    }
}

Simple enough! We created a BufferedReader for the sample file and passed it to CSVParser with a default CSV format. Once we have a CSVParser, we can iterate over all the records one by one using a for loop.

In the above example, We parsed and read one record at a time from the CSV file. The CSVParser class also provides a method called getRecords() to read all the records at once into memory -

// Reading all records at once into memory
List<CSVRecord> csvRecords = csvParser.getRecords();

But you should avoid this method if you’re reading a significantly large CSV file. You might run into memory issues because the getRecords() method loads the entire CSV contents into memory.

Reading a CSV file (Access Values by Names assigned to each column)

In the earlier example, We accessed the values in each record using their column index. If you don’t want to use column indexes to retrieve the values in each record, then you can assign names to each column in the CSV file and retrieve the values using the assigned names.

Check out the following example where we define a manual header and retrieve the values using the header names.

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;

public class CSVReaderWithManualHeader {
    private static final String SAMPLE_CSV_FILE_PATH = "./users.csv";

    public static void main(String[] args) throws IOException {
        try (
            Reader reader = Files.newBufferedReader(Paths.get(SAMPLE_CSV_FILE_PATH));
            CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT
                    .withHeader("Name", "Email", "Phone", "Country")
                    .withIgnoreHeaderCase()
                    .withTrim());
        ) {
            for (CSVRecord csvRecord : csvParser) {
                // Accessing values by the names assigned to each column
                String name = csvRecord.get("Name");
                String email = csvRecord.get("Email");
                String phone = csvRecord.get("Phone");
                String country = csvRecord.get("Country");

                System.out.println("Record No - " + csvRecord.getRecordNumber());
                System.out.println("---------------");
                System.out.println("Name : " + name);
                System.out.println("Email : " + email);
                System.out.println("Phone : " + phone);
                System.out.println("Country : " + country);
                System.out.println("---------------\n\n");
            }
        }
    }
}

Note that we have also specified some additional settings like withIgnoreHeaderCase() and withTrim() with CSVFormat.

The ignoreHeaderCase setting is used make the header names case-insensitive, and the trim setting trims leading and trailing blank spaces from the column values.

Reading a CSV file with Header Auto-detection (Access Values by Header names)

In this example, we’ll read the Sample CSV file that contains a header - users-with-header.csv.

It’s very easy to read such CSV files with Apache Commons CSV. You just need to add a single setting called withFirstRecordAsHeader().

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;

public class CSVReaderWithHeaderAutoDetection {
    private static final String SAMPLE_CSV_FILE_PATH = "./users-with-header.csv";

    public static void main(String[] args) throws IOException {
        try (
            Reader reader = Files.newBufferedReader(Paths.get(SAMPLE_CSV_FILE_PATH));
            CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT
                    .withFirstRecordAsHeader()
                    .withIgnoreHeaderCase()
                    .withTrim());
        ) {
            for (CSVRecord csvRecord : csvParser) {
                // Accessing values by Header names
                String name = csvRecord.get("Name");
                String email = csvRecord.get("Email");
                String phone = csvRecord.get("Phone");
                String country = csvRecord.get("Country");

                System.out.println("Record No - " + csvRecord.getRecordNumber());
                System.out.println("---------------");
                System.out.println("Name : " + name);
                System.out.println("Email : " + email);
                System.out.println("Phone : " + phone);
                System.out.println("Country : " + country);
                System.out.println("---------------\n\n");
            }
        }
    }

}

Apache Commons CSV uses the first record as the header record and allows you to retrieve the values using the header names.

Generating a CSV file

Finally, Let’s see an example of generating a CSV file with Apache Commons CSV.

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

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;

public class CSVWriter {
    private static final String SAMPLE_CSV_FILE = "./sample.csv";

    public static void main(String[] args) throws IOException {
        try (
            BufferedWriter writer = Files.newBufferedWriter(Paths.get(SAMPLE_CSV_FILE));

            CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT
                    .withHeader("ID", "Name", "Designation", "Company"));
        ) {
            csvPrinter.printRecord("1", "Sundar Pichai ♥", "CEO", "Google");
            csvPrinter.printRecord("2", "Satya Nadella", "CEO", "Microsoft");
            csvPrinter.printRecord("3", "Tim cook", "CEO", "Apple");

            csvPrinter.printRecord(Arrays.asList("4", "Mark Zuckerberg", "CEO", "Facebook"));

            csvPrinter.flush();            
        }
    }
}

The above program will generate the following CSV file -

ID,Name,Designation,Company
1,Sundar Pichai ♥,CEO,Google
2,Satya Nadella,CEO,Microsoft
3,Tim cook,CEO,Apple
4,Mark Zuckerberg,CEO,Facebook

Conclusion

That’s all folks. In this article, We learned how to read and write CSV files in Java using Apache Commons CSV library.

You can find all the code samples presented in this article in my github repository.

I have also written an article on How to read and write CSV files using OpenCSV library. Don’t forget to check that out as well.

As always, Thank you for reading. See you in the next post.