CSV stands for ‘comma-separated values‘. CSV files are mostly used for creating data files for exporting or importing the data. Java language does not provide any native support for effectively handling CSV files. Without using 3rd party libraries, we may end up creating your own CSV parser. There is usually no advantage in re-inventing the wheel, so using such 3rd party tools for parsing the CSV files is advisable.
OpenCSV is a tool that can be used to read a CSV file in java or write data to a CSV file.
1. Setting Up
If we are working on a Maven project, we can include the latest OpenCSV maven dependency in pom.xml file like below.
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.7.0</version>
</dependency>
In this tutorial, we will be reading and writing the following file in all examples. We have placed this file in the application’s /resources folder.
ID,FNAME,LNAME,COUNTRY,AGE
1,Lokesh,Gupta,India,32
2,David,Miller,England,34
2. OpenCSV Core Classes
Below is a list of the most used OpenCSV classes which we should go through.
- CSVParser: A very simple CSV parser released under a commercial-friendly license. This just implements splitting a single line into fields.
- CSVReader: You will be using this class most of the time while reading a CSV file from your java application code. This class provides a number of useful constructors to build CSVReader with different options and capabilities. e.g. you can supply a different separator character (default is comma), a different quote character (default is double-quote) and even you can supply the initial line number from where parsing should start.
- CSVWriter: CSVWriter is also very customizable just like
CSVReader. You can use custom separator, custom quote character or custom line terminator while writing a CSV file using your java application code. - CsvToBean: This class will be used when you want to populate your java beans from a CSV file content. You will see an example below.
- BeanToCsv: If you want to export data to CSV file from your java application, you might need help of this class as well.
- ColumnPositionMappingStrategy: If you plan to use CsvToBean (or BeanToCsv) for importing CSV data, you will use this class to map CSV fields to java bean fields.
3. Parsing and Reading a CSV File
3.1. Reading a CSV file Line by Line
As mentioned above, to read a CSV file we will take the help of CSVReader class. Let’s look at a quick example for reading a CSV file line by line.
- We can use CSVParserBuilder to supply any custom seperator character.
- We can use CSVReaderBuilder to specify the number of lines to skip. This is useful is the CSV file has headers in the first row and we do not wish to read headers.
import com.opencsv.CSVParser;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import java.io.FileReader;
import java.net.URL;
import java.util.Arrays;
public class ParseCSVLineByLine {
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
URL fileUrl = ParseCSVLineByLine.class.getClassLoader().getResource("data.csv");
//Build reader instance
//Read data.csv
//Default separator is comma
//Start reading from line number 2 (line numbers start from zero)
CSVParser csvParser = new CSVParserBuilder()
.withSeparator(',')
.withIgnoreQuotations(true)
.build();
CSVReader csvReader = new CSVReaderBuilder(new FileReader(fileUrl.getFile()))
.withSkipLines(1)
.withCSVParser(csvParser)
.build();
//Read CSV line by line and use the string array as you want
String[] nextLine;
while ((nextLine = csvReader.readNext()) != null) {
if (nextLine != null) {
//Verifying the read data here
System.out.println(Arrays.toString(nextLine));
}
}
}
}
3.2. Reading Complete CSV File and Iterating through Lines
The above example read the CSV file line by line and print to the console. We can read the complete CSV file once and then iterate over data as we want. Below is an example of building CSV data read using readAll() method.
import com.opencsv.CSVReader;
import java.io.FileReader;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
public class ParseFullCSVExample {
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
URL fileUrl = ParseCSVLineByLine.class.getClassLoader().getResource("data.csv");
//Build reader instance
CSVReader reader = new CSVReader(new FileReader(fileUrl.getFile()));
//Read all rows at once
List<String[]> allRows = reader.readAll();
//Read CSV line by line and use the string array as you want
for (String[] row : allRows) {
System.out.println(Arrays.toString(row));
}
}
}
4. Writing into a CSV File
Writing a CSV file is as simple as reading it. Create an instance of CSVWriter with appropriate configuration options and start writing data to CSV file.
Notice the optional second argument in writeNext(nextLine, applyQuotesToAll). When we set applyQuotesToAll to true then all the values written in the CSV file are without double quotes.
import com.opencsv.CSVWriter;
import java.io.FileWriter;
import java.net.URL;
public class WritingCSVFileExample {
public static void main(String[] args) throws Exception {
URL fileUrl = WritingCSVFileExample.class.getClassLoader().getResource("data.csv");
CSVWriter writer = new CSVWriter(new FileWriter(fileUrl.getFile()));
//Create record
String[] record = "2,Rahul,Vaidya,India,35".split(",");
//Write the record to file
writer.writeNext(record, false);
//close the writer
writer.close();
}
}
5. Appending to an Existing CSV file
The previous example creates a new CSV file and starts writing data from start i.e. line number 0. Many times we want to append data to an existing CSV file instead of writing a new file. We can achieve this functionality by passing the append mode as the second argument to FileWriter instance.
CSVWriter writer = new CSVWriter(new FileWriter(fileUrl.getFile(), true));
There is no direct support for appending in OpenCSV library.
import com.opencsv.CSVWriter;
import java.io.FileWriter;
import java.net.URL;
public class WritingCSVFileExample {
public static void main(String[] args) throws Exception {
URL fileUrl = WritingCSVFileExample.class.getClassLoader().getResource("data.csv");
CSVWriter writer = new CSVWriter(new FileWriter(fileUrl.getFile(), true));
//Create record
String[] record = new String[]{"3","Rahul","Vaidya","India","35"};
//Write the record to file
writer.writeNext(record, false);
//close the writer
writer.close();
}
}
Now check the data.csv file.
ID,FNAME,LNAME,COUNTRY,AGE
1,Lokesh,Gupta,India,32
2,David,Miller,England,34
3,Rahul,Vaidya,India,35
7. Reading CSV to Java Bean
OpenCSV also provides functionality to read CSV files to Java beans directly. Suppose the Java POJO is Employee class. For keeping things simple, we are creating all fields of String type.
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee
{
private String id;
private String firstName;
private String lastName;
private String country;
private String age;
}
Below example read the data.csv file and populate the instances of Employee. Then it verifies the data by printing it on the console.
import com.opencsv.CSVReader;
import com.opencsv.bean.ColumnPositionMappingStrategy;
import com.opencsv.bean.CsvToBean;
import java.io.FileReader;
import java.net.URL;
import java.util.List;
public class CSVMappedToJavaBeanExample {
@SuppressWarnings({"rawtypes", "unchecked"})
public static void main(String[] args) throws Exception {
URL fileUrl = CSVMappedToJavaBeanExample.class.getClassLoader().getResource("data.csv");
CSVReader csvReader = new CSVReader(new FileReader(fileUrl.getFile()));
CsvToBean csv = new CsvToBean();
csv.setCsvReader(csvReader);
csv.setMappingStrategy(setColumMapping());
List list = csv.parse();
for (Object object : list) {
Employee employee = (Employee) object;
System.out.println(employee);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static ColumnPositionMappingStrategy setColumMapping() {
ColumnPositionMappingStrategy strategy = new ColumnPositionMappingStrategy();
strategy.setType(Employee.class);
String[] columns = new String[]{"id", "firstName", "lastName", "country", "age"};
strategy.setColumnMapping(columns);
return strategy;
}
}
Program Output.
Employee(id=ID, firstName=FNAME, lastName=LNAME, country=COUNTRY, age=AGE)
Employee(id=1, firstName=Lokesh, lastName=Gupta, country=India, age=32)
Employee(id=2, firstName=David, lastName=Miller, country=England, age=34)
Employee(id=3, firstName=Rahul, lastName=Vaidya, country=India, age=35)
8. Creating CSV from SQL Data
Now, this is also a desired activity we will need in the applications. For exporting data directly from SQL tables to CSV files, we will need the ResultSet object. The following API can be used to write data to CSV from ResultSet using obtained ResultSet reference.
java.sql.ResultSet myResultSet = getResultSetFromSomewhere();
writer.writeAll(myResultSet, includeHeaders); //writer is instance of CSVWriter
In the above method, the first argument is the ResultSet which we want to write to CSV file. And the second argument is boolean which represents whether we want to write header columns (table column names) to file or not.
9. Conclusion
This tutorial explained the basic usage of the OpenCSV library to read and write CSV files from a Java application code. We learned to read a CSV file line by line, and whole file in one go. We also learned to configure the reader to supply custom separator and skipping lines incase the file has column names header as first line.
Finally, we learned to write the CSV data into a new File, and appending to an existing CSV file.
Happy Learning !!
I am new to Selenium Webdriver Testng and trying to Develop Data Driven framework using CSVReader
I have 5 tests in Testng and have to run those all on different environments. So basically I have to pick a different url and client, but other pages, elements remain same.
My Question is, Where do I put while loop so that it reads first line and execute all the tests and then read second line and so on.
I tried initialize CSV reader at class level, before suite, before method etc. but it throws error, it works for a particular test if I am putting insside @Test but that doesn’t resolve the purpose, I couldn’t find any relevant answer on the internet.
Please note that for Android, mapping to a java bean does not work due to Android missing the class “java.beans.Introspector”. You can use reader.readAll() and then take it from there.
Open CSV is writing just the column headers on to the CSV file but not the table content. But while I’m printing the values, entire table is printing through my java program. How to fix this? Please help.
You can find my code here – https://stackoverflow.com/questions/39180736/opencsv-sql-writes-only-the-header-and-not-the-table-content
CSVReader reader = new CSVReader(new FileReader(“data.csv”), ‘,’ , ‘”‘ , 1);
reader.readNext() doesn’t work properly when one of the columns data has special characters as input such as below
“~!@#$%^&*()_+`[]{}|:””;,./{}|{}|+*&%#@~\”
Does anybody know how to handle csv columns parsing in this case?
Hi Lokesh,
Is there any solution for this question? I am also facing the same issue.
Hi Lokesh,
Is there any solution for this question? I am also facing the same issue.
Hi,
I don’t see in this tutorial and can’t find on the web any example of usage of BeanToCsv class.
Can someone provide this ?
Thanks
Good tutorial, seems pretty clearly organized. I would however, have 2 questions for you based on this material:
1. Would it possible to apply the same mapping from CSV directly to Java bean in case of having non-String fields? For example if the employee ID and the Employee age were declared integers, would the same mapping presented here be valid?
2. How would it be possible to export data using OpenCSV into HTML format?
1) I believe it should. Can you please try and confirm?
2) I am not sure, because OpenCSV is not for reporting purpose.
what is the parse method in class CSVMappedToJavaBeanExample.java as it is not defined in Employee class.
List list = csv.parse(setColumMapping(), csvReader);
Hello Sir,
This information is very useful. However, in my requirement, I need to ignore the occurrence of delimiter in the last string I get from CSV. Can you give an example how it could be done?
Thanks & regards,
Santhosh Kumar.
Not sure what you are looking for. Can you please give some sample CSV which you want to read/escape?
First Name;;; Last Name; City; Address;; zip code;; and this \n is the \n additional; text; as \n a last string
Thank you for your reply Lokesh. Consider the above row as text in the CSV file. In this case, using “;” as delimiter, I can get the strings. But in the last string mentioned in brackets, (and this \n is the \n additional; text; as \n a last string), I dont want the delimition to happen. This is what I am looking for. In this case, I cannot use “\” as escape character as \n would not work. Please help. Thanks in advance
You can do only those things with code which you logically implement in steps. In your case, probably you first need to use the delimiter ‘and’ or any such word. This will divide you string into two parts. You can again tokenize the first part with delimiter ‘;’ and leave the second part.
If you can not break your logic into logical steps, you will not be able to write the code for it as well. So please try to create logical steps first, and then let me know for which part you want me to help in writing code.
I hope I make sense.
Hi,
I would like to write mutiple resultsets into a csv file. How can I do that? Is there anyway I can write in next tabs?
Please advice.
Thanks,
Sivaprasath
Sir,
If my bean class has reference of other Class then how do I bind csv to my bean class, consider following example :
public class Employee{
private int empId;
private int empName;
private Address address;
}
public class Address {
private String city;
private String state;
}
And my Employee.csv file is like this :
EmpId,EmpName,City,State
101,xyz,abc,def
Please clarify
Tricky question. I will take some time to do some research on it.
Hi Lokesh,
Could you please tell that how we could populate Address in Employee object .
I need to populate Address values in address of Employee entity.
Thanks & Regards,
Raja Sekhar.
Can POI also read CSV files or just Excel?
Apache POI was never designed to call on CSV files. While a CSV File may be opened in Excel, Excel has its own reader that does an auto import. For CSV file, OpenCSV is better option.