Opencsv
last modified July 4, 2024
In this article we show how to work with the Opencsv library which is used to read and write CSV files in Java. We provide several code examples to work with CSV in Java.
CSV (Comma Separated Values) format is a very popular import and export format used in spreadsheets and databases.
Each line in a CSV file is a data record. Each record consists of one or more fields, separated by commas. Despite CSV format being a very simple format, there can be many differecies, such as different delimiters, new lines, or quoting characters.
Opencsv library
Opencsv is a very simple CSV parser library for Java. It was developed because of the lack of commercial-friendly licenses.
<dependencies> <dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.9</version> </dependency> </dependencies>
This is the Maven dependency for Opencsv.
Reading data
The following example reads numbers from a CSV file.
3,5,6,2,1,7,8 4,5,7,3,2,8,9
We have two records of data in the numbers.csv
file.
import com.opencsv.CSVReader; import com.opencsv.exceptions.CsvValidationException; import java.io.FileReader; import java.io.IOException; import java.nio.charset.StandardCharsets; void main() throws IOException, CsvValidationException { var fileName = "src/main/resources/numbers.csv"; try (var fr = new FileReader(fileName, StandardCharsets.UTF_8); var reader = new CSVReader(fr)) { String[] nextLine; while ((nextLine = reader.readNext()) != null) { for (var e : nextLine) { System.out.format("%s ", e); } } } }
The example reads numbers from the numbers.csv
file and prints
them to the console.
var fileName = "src/main/resources/numbers.csv";
The file is located in the src/main/resources
directory.
try (var fr = new FileReader(fileName, StandardCharsets.UTF_8); var reader = new CSVReader(fr)) {
The CSVReader
is a class used for reading CSV files.
while ((nextLine = reader.readNext()) != null) { for (String e: nextLine) { System.out.format("%s ", e); } }
We iterate through the reader and print the value to the terminal. The
readNext
method reads the next line from the buffer and converts
to a string array.
Reading with different separator
Despite its name, CSV files can be separated with a delimiter other than a comma. The following example shows how to read numbers separated by a pipe | character.
1|2|3|4|5 6|7|3|9|8 9|1|1|0|2
We have three rows of numbers separated with the | character.
import com.opencsv.CSVParser; import com.opencsv.CSVParserBuilder; import com.opencsv.CSVReaderBuilder; import com.opencsv.exceptions.CsvException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; void main() throws IOException, CsvException { var fileName = "src/main/resources/numbers.csv"; Path myPath = Paths.get(fileName); CSVParser parser = new CSVParserBuilder().withSeparator('|').build(); try (var br = Files.newBufferedReader(myPath, StandardCharsets.UTF_8); var reader = new CSVReaderBuilder(br).withCSVParser(parser) .build()) { List<String[]> rows = reader.readAll(); for (String[] row : rows) { for (String e : row) { System.out.format("%s ", e); } System.out.println(); } } }
The example reads values from the numbers.csv
file and prints them
to the console.
CSVParser parser = new CSVParserBuilder().withSeparator('|').build();
A CSVParser
with specific parser character is created.
try (var br = Files.newBufferedReader(myPath, StandardCharsets.UTF_8); var reader = new CSVReaderBuilder(br).withCSVParser(parser) .build()) {
A CSVReader
is created with CSVReaderBuilder
.
List<String[]> rows = reader.readAll();
We read all the elements into a list in one shot with the readAll
method. This method should not be used for large files.
Writing data
The CSVWriter
class is used to write data to a CSV file.
import com.opencsv.CSVWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; void main() throws IOException { String[] entries = { "book", "coin", "pencil", "cup" }; String fileName = "src/main/resources/items.csv"; try (var fos = new FileOutputStream(fileName); var osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); var writer = new CSVWriter(osw)) { writer.writeNext(entries); } }
The example writes data from an array to the items.csv
file.
The file is written into the project root directory. The writeNext
method writes an array of elements to the file.
In the next code example, we write all data in one shot.
import com.opencsv.CSVWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; void main() throws IOException { String[] items1 = {"book", "coin", "pencil"}; String[] items2 = {"pen", "chair", "lamp"}; String[] items3 = {"ball", "bowl", "spectacles"}; List<String[]> entries = new ArrayList<>(); entries.add(items1); entries.add(items2); entries.add(items3); String fileName = "src/main/resources/items.csv"; try (var fos = new FileOutputStream(fileName); var osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); var writer = new CSVWriter(osw)) { writer.writeAll(entries); } }
The example writes a list of arrays to the items.csv
file
using the writeAll
method.
SQL data to CSV file
The following example retrieves data from a database table and writes it into a CSV file. We use PostgreSQL database.
In addition to the opencsv
artifact, we also need the
postgresql
driver artifact.
-- SQL for the cars table CREATE TABLE cars(id serial PRIMARY KEY, name VARCHAR(255), price INT); INSERT INTO cars(name, price) VALUES('Audi', 52642); INSERT INTO cars(name, price) VALUES('Mercedes', 57127); INSERT INTO cars(name, price) VALUES('Skoda', 9000); INSERT INTO cars(name, price) VALUES('Volvo', 29000); INSERT INTO cars(name, price) VALUES('Bentley', 350000); INSERT INTO cars(name, price) VALUES('Citroen', 21000); INSERT INTO cars(name, price) VALUES('Hummer', 41400); INSERT INTO cars(name, price) VALUES('Volkswagen', 21600);
This is the Cars
table from which we retrieve the
data.
import com.opencsv.CSVWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.sql.DriverManager; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; void main() { String url = "jdbc:postgresql://localhost:5432/testdb"; String user = "postgres"; String password = "s$cret"; String fileName = "src/main/resources/cars.csv"; Path myPath = Paths.get(fileName); try (var con = DriverManager.getConnection(url, user, password); var pst = con.prepareStatement("SELECT * FROM cars"); var rs = pst.executeQuery()) { try (var writer = new CSVWriter(Files.newBufferedWriter(myPath, StandardCharsets.UTF_8), CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.NO_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END)) { writer.writeAll(rs, true); } } catch (SQLException | IOException ex) { Logger.getLogger(getClass().getName()).log( Level.SEVERE, ex.getMessage(), ex); } }
In the example, we connect to the PostgreSQL database and retrieve all rows
from the Cars
table. The data is written to the
cars.csv
file.
try (var con = DriverManager.getConnection(url, user, password); var pst = con.prepareStatement("SELECT * FROM cars"); var rs = pst.executeQuery()) {
We connect to the database table with the driver manager and execute the
SELECT * FROM cars
statement.
try (var writer = new CSVWriter(Files.newBufferedWriter(myPath, StandardCharsets.UTF_8), CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.NO_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END)) { writer.writeAll(rs, true); }
We create a CSVWriter
with a default separator, no quoting
characters, no escape character, and a default line end.
writer.writeAll(rs, true);
The writeAll
method takes the java.sql.ResultSet
as a parameter. The second parameter specifies whether the field headers
should be included.
Opencsv mapping to JavaBeans
CsvToBean
is used to map CSV data to JavaBeans.
Mapping by column names
With HeaderColumnNameMappingStrategy
, we can map CSV data to Java
objects using the column names in the first row of the CSV file
id,name,price 1,Audi,52642 2,Mercedes,57127 3,Skoda,9000 4,Volvo,29000 5,Bentley,350000 6,Citroen,21000 7,Hummer,41400 8,Volkswagen,21600 9,Toyota,26700
This is the cars.csv
file. The first record contains the
column names.
import com.opencsv.bean.CsvBindByName; public class Car { @CsvBindByName private int id; @CsvBindByName private String name; @CsvBindByName private int price; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public String toString() { var builder = new StringBuilder(); builder.append("Car{id=").append(id).append(", name=") .append(name).append(", price=").append(price).append("}"); return builder.toString(); } }
The Car
is a JavaBean. It contains the
@CsvBindByName
annotations to map the bean attributes
to the CSV columns.
import com.opencsv.bean.CsvToBean; import com.opencsv.bean.CsvToBeanBuilder; import com.opencsv.bean.HeaderColumnNameMappingStrategy; import java.io.BufferedReader; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; void main() throws IOException { String fileName = "src/main/resources/cars.csv"; Path myPath = Paths.get(fileName); try (BufferedReader br = Files.newBufferedReader(myPath, StandardCharsets.UTF_8)) { HeaderColumnNameMappingStrategy<Car> strategy = new HeaderColumnNameMappingStrategy<>()> strategy.setType(Car.class); CsvToBean<Car> csvToBean = new CsvToBeanBuilder<Car>(br) .withMappingStrategy(strategy) .withIgnoreLeadingWhiteSpace(true) .build(); List<Car> cars = csvToBean.parse(); cars.forEach(System.out::println); } }
The example reads the data from the cars.csv
file and
maps them to the Car
objects. It uses HeaderColumnNameMappingStrategy
.
HeaderColumnNameMappingStrategy<Car> strategy = new HeaderColumnNameMappingStrategy<>(); strategy.setType(Car.class);
The HeaderColumnNameMappingStrategy
maps data to objects using
the column names in the first row of the CSV file. The column order does not matter.
CsvToBean<Car> csvToBean = new CsvToBeanBuilder<Car>(br) .withMappingStrategy(strategy) .withIgnoreLeadingWhiteSpace(true) .build();
A CsvToBean
is created with CsvToBeanBuilder
. We
specify the mapping strategy.
List<Car> cars = csvToBean.parse();
With the CsvToBean's
parse
method, we parse the CSV data
into the list.
cars.forEach(System.out::println);
We go over the list of beans and print them to the console.
Mapping by column position
The ColumnPositionMappingStrategy
maps columns by their position.
1,Audi,52642 2,Mercedes,57127 3,Skoda,9000 4,Volvo,29000 5,Bentley,350000 6,Citroen,21000 7,Hummer,41400 8,Volkswagen,21600 9,Toyota,26700
This is the cars.csv
file.
import com.opencsv.bean.CsvBindByPosition; public class Car { @CsvBindByPosition(position = 0) private int id; @CsvBindByPosition(position = 1) private String name; @CsvBindByPosition(position = 2) private int price; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public String toString() { var builder = new StringBuilder(); builder.append("Car{id=").append(id).append(", name=") .append(name).append(", price=").append(price).append("}"); return builder.toString(); } }
The @CsvBindByPosition
specifies a binding between a column
number of the CSV input and a field in a bean.
import com.opencsv.bean.ColumnPositionMappingStrategy; import com.opencsv.bean.CsvToBean; import com.opencsv.bean.CsvToBeanBuilder; import java.io.BufferedReader; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; void main() throws IOException { String fileName = "src/main/resources/cars.csv"; Path myPath = Paths.get(fileName); try (BufferedReader br = Files.newBufferedReader(myPath, StandardCharsets.UTF_8)) { ColumnPositionMappingStrategy<Car> strategy = new ColumnPositionMappingStrategy<>(); strategy.setType(Car.class); String[] fields = {"id", "name", "price"}; strategy.setColumnMapping(fields); CsvToBean<Car> csvToBean = new CsvToBeanBuilder<Car>(br) .withMappingStrategy(strategy) .withIgnoreLeadingWhiteSpace(true) .build(); List<Car> cars = csvToBean.parse(); cars.forEach(System.out::println); } }
The example reads the data from the cars.csv
file and
maps them to the Car
objects. It uses ColumnPositionMappingStrategy
.
ColumnPositionMappingStrategy<Car> strategy = new ColumnPositionMappingStrategy<>(); strategy.setType(Car.class); String[] fields = {"id", "name", "price"}; strategy.setColumnMapping(fields);
We create a ColumnPositionMappingStrategy
. With setColumnMapping
we set the column names to be mapped.
Opencsv writing JavaBeans with StatefulBeanToCsv
In the next example, we write JavaBeans to CSV with StatefulBeanToCsv
.
public class Car { private int id; private String name; private int price; public Car() { } public Car(int id, String name, int price) { this.id = id; this.name = name; this.price = price; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public String toString() { var builder = new StringBuilder(); builder.append("Car{id=").append(id).append(", name=") .append(name).append(", price=").append(price).append("}"); return builder.toString(); } }
This is a Car
bean.
import com.opencsv.CSVWriter; import com.opencsv.bean.StatefulBeanToCsv; import com.opencsv.bean.StatefulBeanToCsvBuilder; import com.opencsv.exceptions.CsvDataTypeMismatchException; import com.opencsv.exceptions.CsvRequiredFieldEmptyException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; void main() { String fileName = "src/main/resources/cars.csv"; Path myPath = Paths.get(fileName); var cars = List.of(new Car(1, "Audi", 52642), new Car(2, "Mercedes", 57127), new Car(3, "Skoda", 9000), new Car(4, "Volvo", 29000)); try (var writer = Files.newBufferedWriter(myPath, StandardCharsets.UTF_8)) { StatefulBeanToCsv<Car> beanToCsv = new StatefulBeanToCsvBuilder<Car>(writer) .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER) .build(); beanToCsv.write(cars); } catch (CsvDataTypeMismatchException | CsvRequiredFieldEmptyException | IOException ex) { Logger.getLogger(getClass().getName()).log( Level.SEVERE, ex.getMessage(), ex); } }
The example creates a list of car objects and writes them to a CSV file.
var cars = List.of(new Car(1, "Audi", 52642), new Car(2, "Mercedes", 57127), new Car(3, "Skoda", 9000), new Car(4, "Volvo", 29000));
We create a list of car objects.
StatefulBeanToCsv<Car> beanToCsv = new StatefulBeanToCsvBuilder<Car>(writer) .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER) .build();
A StatefulBeanToCsv
is created with StatefulBeanToCsvBuilder
.
beanToCsv.write(cars);
The beans are written to a file.
In this article we have worked with the Opencsv library. We have read data from a CSV file, written data to a CSV file, exported data from a database table to a CSV file, and mapped CSV data to beans.
Source
Author
List all Java tutorials.