# How to read and write CSV files using OpenCSV

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Sep 15, 2019, updated Sep 24, 2022. Topics: Java, CSV.
Canonical URL: https://attacomsian.com/blog/read-write-csv-files-opencsv

> A comprehensive guide to reading and writing CSV files using a popular open-source library OpenCSV in Java. Learn how to read CSV files as an array of strings or map CSV columns directly to Java objects.

In an [earlier article](https://attacomsian.com/blog/read-write-csv-files-apache-commons-csv), I discussed how to read and write CSV files using Apache Commons CSV. This article is a direct continuation of the previous article and part of the series about libraries that can be used to read and write CSV files in Java.

Today, we shall learn about another open-source library, [OpenCSV](http://opencsv.sourceforge.net/), to read and write CSV files in Java. OpenCSV is another popular library for reading, writing, parsing, serializing, and deserializing CSV files in Java.

## Dependencies

Before we move on to parsing or writing CSV files, you only need OpenCSV dependency for your project. If you are using Gradle, add the following dependency to the `build.gradle` file:

```groovy
implementation 'com.opencsv:opencsv:4.6'
```

For the Maven project, you should add the below dependency to the `pom.xml` file:

```xml
<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>4.6</version>
</dependency>
```

## Sample CSV Files

Let us use the same CSV files we used for the Commons CSV examples for reading and parsing using OpenCSV. 

Here is the first CSV **without a header**:

<p class="file-desc"><span>users.csv</span></p>

```csv
1,Atta Shah,atta@example.com,PK
2,Alex Jones,alex@example.com,DE
3,Jovan Lee,jovan@example.com,FR
4,Greg Hover,greg@example.com,US
```

The second CSV file **with a header**:

<p class="file-desc"><span>users-with-header.csv</span></p>

```csv
id,name,email,country
1,Atta Shah,atta@example.com,PK
2,Alex Jones,alex@example.com,DE
3,Jovan Lee,jovan@example.com,FR
4,Greg Hover,greg@example.com,US
```

## Reading CSV Files

There are multiple ways to read a CSV file with OpenCSV. You can choose to read the CSV file either line-by-line or at once. 

Similarly, you can decide whether to read the record as a string array or bind the record into an object. Let us look at all these approaches below.

### Reading a CSV file with each record as a string array

The simplest way to read a CSV file using OpenCSV is by reading each record into a string array. Here is an example that uses the `CSVReader` class to read one line at a time from the file:

```java
try {
    // create a reader
    Reader reader = Files.newBufferedReader(Paths.get("users.csv"));

    // create csv reader
    CSVReader csvReader = new CSVReader(reader);

    // read one record at a time
    String[] record;
    while ((record = csvReader.readNext()) != null) {
        System.out.println("ID: " + record[0]);
        System.out.println("Name: " + record[1]);
        System.out.println("Email: " + record[2]);
        System.out.println("Country: " + record[3]);
    }

    // close readers
    csvReader.close();
    reader.close();

} catch (IOException ex) {
    ex.printStackTrace();
}
```

#### Reading all records at once

In the example above, the `readNext()` method reads the next line from the buffer and converts it to a string array. The `CSVReader` class also provides a method called `readAll()` that reads the entire file into a `List` with each element being a `String[]` of tokens:

```java
try {
    // create a reader
    Reader reader = Files.newBufferedReader(Paths.get("users.csv"));

    // create csv reader
    CSVReader csvReader = new CSVReader(reader);

    // read all records at once
    List<String[]> records = csvReader.readAll();

    // iterate through the list of records
    for (String[] record : records) {
        System.out.println("ID: " + record[0]);
        System.out.println("Name: " + record[1]);
        System.out.println("Email: " + record[2]);
        System.out.println("Country: " + record[3]);
    }

    // close readers
    csvReader.close();
    reader.close();

} catch (IOException ex) {
    ex.printStackTrace();
}
```

The above approach is not recommended for larger CSV files as it loads the entire file contents into memory.

#### Skipping the header

There is no way to skip the header record when using the `CSVReader` class. If you read a file that contains a header, then the header will also be printed on the console.
 
Instead, you should use `CSVReaderBuilder`, which provides greater flexibility and more configuration options, including the ability to skip the header record.

Let us use the `CSVReaderBuilder` class to create a `CSVReader` object with a specified number of records skipped:

```java
CSVReader csvReader = new CSVReaderBuilder(reader).withSkipLines(1).build();
```

`CSVParserBuilder` allows you to choose a custom column separator, ignore or handle quotations marks, decide what to do with `null` fields, and how to interpret escaped characters:

```java
CSVParser parser = new CSVParserBuilder()
        .withSeparator('\t')
        .withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_QUOTES)
        .withIgnoreLeadingWhiteSpace(true)
        .withIgnoreQuotations(false)
        .withStrictQuotes(true)
        .build();

CSVReader csvReader = new CSVReaderBuilder(reader)
        .withSkipLines(1)
        .withCSVParser(parser)
        .build();
```

Check out the [official documentation](http://opencsv.sourceforge.net/apidocs/index.html) for more information on these configuration options.

### Reading a CSV file with each record as a Java object using annotations

The real benefit of using OpenCSV is that you can directly map the record fields into a Java object. There are two ways of doing this. You can use annotations or mapping strategies to bind the record fields to bean attributes.

OpenCSV has **two types of annotations** to specify the column names mapping with object fields either by name or by position: `@CsvBindByName` and `@CsvBindByPosition`.

#### Using `@CsvBindByName` annotation

You can only use the `@CsvBindByName` annotation if the CSV file has a header. It accepts up to five parameters, including `column`, `required`, and `locale`. All parameters are options except `column`, which is also only *required* if the header column name in the CSV file is different from the bean field.

Let us first create a Java class to make use of the `CsvBindByName` annotation:

<p class="file-desc"><span>User.java</span></p>

```java
public class User {

    @CsvBindByName
    public int id;
    @CsvBindByName
    public String name;
    @CsvBindByName
    public String email;
    @CsvBindByName(column = "country")
    public String countryCode;

    // getters and setters omitted for brevity
}
```

Here is an example that reads and parses the CSV file records directly into Java objects using OpenCSV:

```java
try {
    // create a reader
    Reader reader = Files.newBufferedReader(Paths.get("users-with-header.csv"));

    // create csv bean reader
    CsvToBean csvToBean = new CsvToBeanBuilder(reader)
            .withType(User.class)
            .withIgnoreLeadingWhiteSpace(true)
            .build();

    // iterate through users
    for (User user : (Iterable<User>) csvToBean) {
        System.out.println("ID: " + user.getId());
        System.out.println("Name: " + user.getName());
        System.out.println("Email: " + user.getEmail());
        System.out.println("Country: " + user.getCountryCode());
    }

    // close the reader
    reader.close();

} catch (IOException ex) {
    ex.printStackTrace();
}
```

Note that we used the `users-with-headers.csv` file for the above example because it contains a header.

The `CsvToBean` class also provides a `parse()` method that reads entire CSV file contents into memory and then parses it into a list of objects (not recommended for large CSV files):

```java
List<User> users = csvToBean.parse();

// iterate through list
for (User user : users) {
    System.out.println("ID: " + user.getId());
    System.out.println("Name: " + user.getName());
    System.out.println("Email: " + user.getEmail());
    System.out.println("Country: " + user.getCountryCode());
}
```

#### Using `@CsvBindByPosition` annotation

If the CSV file does not have a header, you use the `@CsvBindByPosition` annotation to map the column position (zero-based) to bean fields like the below:

```java
public class User {

    @CsvBindByPosition(position = 0)
    public int id;
    @CsvBindByPosition(position = 1)
    public String name;
    @CsvBindByPosition(position = 2)
    public String email;
    @CsvBindByPosition(position = 3)
    public String countryCode;

    // getters and setters omitted for brevity
}
```

### Reading a CSV file with each record as a Java object using mapping strategies

Mapping strategies are another way of mapping the CSV columns directly to Java object fields. Using this strategy, you can safely remove all OpenCSV annotations from your Java classes.

Let us first remove all annotations from the `User` class:

```java
public class User {

    public int id;
    public String name;
    public String email;
    public String countryCode;

    public User(int id, String name, String email, String countryCode) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.countryCode = countryCode;
    }

    // getters and setters omitted for brevity
}
```

Now let us use `ColumnPositionMappingStrategy` to specify the mapping between CSV columns and Java object attributes and then parse the CSV records into Java objects:

```java
try {
    // create a reader
    Reader reader = Files.newBufferedReader(Paths.get("users-with-header.csv"));

    // columns name
    String[] columns = {"id", "name", "email", "countryCode"};

    // create a mapping strategy
    ColumnPositionMappingStrategy strategy = new ColumnPositionMappingStrategy();
    strategy.setType(User.class);
    strategy.setColumnMapping(columns);

    // create csv bean reader
    CsvToBean csvToBean = new CsvToBeanBuilder(reader)
            .withMappingStrategy(strategy)
            .withSkipLines(1)
            .withIgnoreLeadingWhiteSpace(true)
            .build();

    // iterate through users
    for (User user : (Iterable<User>) csvToBean) {
        System.out.println("ID: " + user.getId());
        System.out.println("Name: " + user.getName());
        System.out.println("Email: " + user.getEmail());
        System.out.println("Country: " + user.getCountryCode());
    }

    // close the reader
    reader.close();

} catch (IOException ex) {
    ex.printStackTrace();
}
```

The `ColumnPositionMappingStrategy` class uses the position of the column in the CSV file to map it to the bean attribute.

## Writing CSV Files

OpenCSV allows you to generate a CSV file from an array of strings or from a list of objects. It has more configuration options than Commons CSV for writing data to CSV files. Most importantly, you can easily convert any list of objects to a CSV file by writing just a few lines of code.

### Generating a CSV file from an array of strings

Here is an example that writes an array of strings to a CSV file by using OpenCSV:

```java
try {
    // create a write
    Writer writer = Files.newBufferedWriter(Paths.get("users-simple.csv"));

    // header record
    String[] headerRecord = {"id", "name", "email", "country"};

    // create a csv writer
    ICSVWriter csvWriter = new CSVWriterBuilder(writer)
            .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
            .withQuoteChar(CSVWriter.NO_QUOTE_CHARACTER)
            .withEscapeChar(CSVWriter.DEFAULT_ESCAPE_CHARACTER)
            .withLineEnd(CSVWriter.DEFAULT_LINE_END)
            .build();

    // write header record
    csvWriter.writeNext(headerRecord);

    // write data records
    csvWriter.writeNext(new String[] {"1", "Emma Watson", "emma.watson@example.com", "UK"});
    csvWriter.writeNext(new String[] {"2", "Nick Jones", "nick.jones@example.com", "DE"});
    csvWriter.writeNext(new String[] {"3", "Shanzay Alai", "shanzay.alai@example.com", "US"});

    // close writers
    csvWriter.close();
    writer.close();

} catch (IOException ex) {
    ex.printStackTrace();
}
```

## Generating a CSV file from a list of objects

Here is an example that shows how to convert a list of objects into a CSV file. It is using the `User` class we defined in the previous example:

```java
try {
    // create a write
    Writer writer = Files.newBufferedWriter(Paths.get("users-objects.csv"));

    // create a csv writer
    StatefulBeanToCsv<User> csvWriter = new StatefulBeanToCsvBuilder<User>(writer)
            .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
            .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
            .withEscapechar(CSVWriter.DEFAULT_ESCAPE_CHARACTER)
            .withLineEnd(CSVWriter.DEFAULT_LINE_END)
            .withOrderedResults(false)
            .build();

    // create a list of objects (`User`)
    List<User> users = new ArrayList<>();
    users.add(new User(1, "Emma Watson", "emma.watson@example.com", "UK"));
    users.add(new User(2, "Nick Jones", "nick.jones@example.com", "DE"));
    users.add(new User(3, "Shanzay Alai", "shanzay.alai@example.com", "US"));

    // write a list of objects
    csvWriter.write(users);

    // close the writer
    writer.close();

} catch (Exception ex) {
    ex.printStackTrace();
}
```

## Conclusion

That is all for reading and writing CSV files in Java using the OpenCSV library. We discussed almost all ways to write and read data from a CSV file. 

OpenCSV is a simple yet very powerful CSV parser that makes it a popular choice for manipulating CSV files in Java.

I appreciate your patience in reading this long article. 

## Further Reading

I hope you enjoy reading this article. You may be interested in reading other CSV-related articles:

* [Reading and writing CSV files using Apache Commons CSV](https://attacomsian.com/blog/read-write-csv-files-apache-commons-csv)
* [Reading and writing CSV files using core Java](https://attacomsian.com/blog/read-write-csv-files-core-java)
* [Export & Download Data as CSV File in Spring Boot](https://attacomsian.com/blog/export-download-data-csv-file-spring-boot)
