Java Read/Write CSV File: Open CSV + Apache Common

Java Read Write CSV File using Open CSV or Apache Common

A CSV is a comma-separated values file, which allows data to be saved in a tabular format. “How to read and write CSV files” is one of the most common question in Java development world. So in the tutorial, I will introduce details how to do it by clearly example coding with 2 libraries: Open CSV and Apache Common.

What we will do?

Using Open CSV to Read CSV file

For reading CSV file by Open CSV, we can do with 4 approaches:

Read CSV File Line by Line

For reading CSV File, we use a CSVReader instance.

BufferedReader fileReader = new BufferedReader(new FileReader(pathfile));
CSVReader csvReader = new CSVReader(fileReader);

For reading a Csv file line by line, we use readNext() method, which reads the next line from the buffer and converts to a string array.

/**
 * 
 * Read CSV file by a way: Line by Line
 * @param pathfile
 */
public static void readCSVFileLineByLine(String pathfile) {
	try(
			BufferedReader fileReader = new BufferedReader(new FileReader(pathfile));
			CSVReader csvReader = new CSVReader(fileReader);	
		)
	{
		String[] record;
        csvReader.readNext(); // skip Header
        while ((record = csvReader.readNext()) != null) {
          System.out.println(record[0] + " | " + record[1] + " | " + record[2] + " | " + record[3]);
        }
        
	} catch(Exception e) {
		System.out.println("Error when reading csv file name = "+ pathfile);
		e.printStackTrace();
	}
}

readNext() returns a string array with each comma-separated element as a separate entry, or null if there is no more input.

customers.csv CSV file:

csv file
csv file

Run the code:


public class ReadCSVFileUsingOpenCsv {
	public static void main(String[] args) {
		String pathfile = "customers.csv";
		readCSVFileLineByLine(pathfile);
	}
        ...

Result:

1 | Jack | jack@gmail.com | 2000
2 | Adam | adam@gmail.com | 2300
3 | Katherin | katherin@gmail.com | 3000
4 | David | david@gmail.com | 4200
5 | Jason | jason@gmail.com | 2500

Read CSV File All Line at One

We can use the method readAll() to read the entire csv file into a List with each element being a String[] of tokens.

Method Signature:

List com.opencsv.CSVReader.readAll() throws IOException

readAll() returns a List of String[], with each String[] representing a line of the file.

public static void readCSVFileAllAtOnce(String pathfile) {
	try(
			BufferedReader fileReader = new BufferedReader(new FileReader(pathfile));
		    CSVReader csvReader = new CSVReader(fileReader);	
		)
	{
		System.out.println("\n--- Read all at once ---");
		List records = csvReader.readAll();

		for (String[] _record : records) {
			System.out.println(_record[0] + " | " + _record[1] + " | " + _record[2] + " | " + _record[3]);
		}			
	} catch(Exception e) {
		System.out.println("Error when reading csv file name = "+ pathfile);
		e.printStackTrace();
	}
}

Run the code:

public class ReadCSVFileUsingOpenCsv {
	public static void main(String[] args) {
		String pathfile = "customers.csv";
		readCSVFileAllAtOnce(pathfile);
                ...
	}

Output in console:

--- Read all at once ---
id | name | email | salary
1 | Jack | jack@gmail.com | 2000
2 | Adam | adam@gmail.com | 2300
3 | Katherin | katherin@gmail.com | 3000
4 | David | david@gmail.com | 4200
5 | Jason | jason@gmail.com | 2500

Read CSV File Using Annotation

Create a Customer class to model data as below:

public class Customer {
	private long id;
	private String name;
	private String email;
	private Long salary;

	public Customer() {
	}

	public Customer(long id, String name, String email, Long salary) {
		this.id = id;
		this.name = name;
		this.email = email;
		this.salary = salary;
	}
        // getters & setters

Now we create a AnnoCustomer class to use an annotation @CsvBindByName to specify a binding between a column name of the CSV input and a field in a bean:

package com.loizenjava.readwritecsv.model;

import com.opencsv.bean.CsvBindByName;

public class AnnoCustomer {
	
	@CsvBindByName
	private long id;

	@CsvBindByName
	private String name;

	@CsvBindByName
	private String email;

	@CsvBindByName
	private Long salary;

	public AnnoCustomer() {
	}

	public AnnoCustomer(long id, String name, String email, Long salary) {
		this.id = id;
		this.name = name;
		this.email = email;
		this.salary = salary;
	}
    
        // getters & setters
        ...

Implement a function readCSVFileUsingAnnotation() to reading CSV file using annotation:

/**
 * Read CSV File using Annotation
 * @param pathfile
 */
public static void readCSVFileUsingAnnotation (String pathfile) {
	try (
			BufferedReader fileReader = new BufferedReader(new FileReader(pathfile))
		) 
	{
		CsvToBean csvToBean = new CsvToBeanBuilder(fileReader)
				.withType(AnnoCustomer.class).withIgnoreLeadingWhiteSpace(true).build();
		
		List customers = csvToBean.parse();

		for (AnnoCustomer customer : customers) {
			System.out.println(customer);
		}
		
	} catch (Exception e) {
		System.out.println("Reading CSV Error!");
		e.printStackTrace();
	}
}

Run the below code:

public class ReadCSVFileUsingOpenCsv {
	public static void main(String[] args) {
		String pathfile = "customers.csv";
		readCSVFileUsingAnnotation(pathfile);
	}

Output:

Customer [id=1, name=Jack, email=jack@gmail.com, salary=2000]
Customer [id=2, name=Adam, email=adam@gmail.com, salary=2300]
Customer [id=3, name=Katherin, email=katherin@gmail.com, salary=3000]
Customer [id=4, name=David, email=david@gmail.com, salary=4200]
Customer [id=5, name=Jason, email=jason@gmail.com, salary=2500]

Read CSV File with Position Mapping Strategy

We can use ColumnPositionMappingStrategy class for mapping the columns with their positions.

Using this strategy without annotations (com.opencsv.bean.CsvBindByPosition or com.opencsv.bean.CsvCustomBindByPosition) requires all the columns to be present in the CSV file and for them to be in a particular order.

Now we implement a function with ColumPositionMappingStrategy as below code:

/**
 * Read CSV File with Mapping Strategy
 * @param pathfile
 */
public static void readCSVFileWithMappingStrategy(String pathfile) {
	String[] CSV_HEADER = { "id", "name", "email", "salary" };
	
	try (BufferedReader fileReader = new BufferedReader(new FileReader(pathfile));) {
		ColumnPositionMappingStrategy mappingStrategy = new ColumnPositionMappingStrategy();

		mappingStrategy.setType(Customer.class);
		mappingStrategy.setColumnMapping(CSV_HEADER);

		CsvToBean csvToBean = new CsvToBeanBuilder(fileReader)
				.withMappingStrategy(mappingStrategy).withSkipLines(1).withIgnoreLeadingWhiteSpace(true).build();

		List customers = csvToBean.parse();

		for (Customer customer : customers) {
			System.out.println(customer);
		}
	} catch (Exception e) {
		System.out.println("Reading CSV Error!");
		e.printStackTrace();
	}
}

We need set type Customer and colum mapping as below to specify an instruction how to map

String[] CSV_HEADER = { "id", "name", "email", "salary" };
...

mappingStrategy.setType(Customer.class);
mappingStrategy.setColumnMapping(CSV_HEADER);

Now run the main function as below:

public static void main(String[] args) {
	String pathfile = "customers.csv";
	readCSVFileWithMappingStrategy(pathfile);
}

Output in console:

Customer[id = 1, name = Jack, email = jack@gmail.com, salary = 2000]
Customer[id = 2, name = Adam, email = adam@gmail.com, salary = 2300]
Customer[id = 3, name = Katherin, email = katherin@gmail.com, salary = 3000]
Customer[id = 4, name = David, email = david@gmail.com, salary = 4200]
Customer[id = 5, name = Jason, email = jason@gmail.com, salary = 2500]

Using Open CSV to Write CSV file

Write String Array to CSV File

It is very simple, we just use the CSVWriter class with a FileWriter and some other configured parameters to write String Array data to a csv file:

Method Signature:

 com.opencsv.CSVWriter.CSVWriter(Writer writer, char separator, char quotechar, char escapechar, String lineEnd)

Parameters:

  • writer The writer to an underlying CSV source.
  • separator The delimiter to use for separating entries
  • quotechar The character to use for quoted elements
  • escapechar The character to use for escaping quotechars or escapechars
  • lineEnd The line feed terminator to use

Now we implement a function writeCSVFileFromStringArray to do the task:

/**
 * Write data to CSV File From String Array
 */
public static void writeCSVFileFromStringArray(List datas, String pathFile) {
	try (FileWriter fileWriter = new FileWriter(pathFile);
			CSVWriter csvWriter = new CSVWriter(fileWriter, CSVWriter.DEFAULT_SEPARATOR,
					CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.DEFAULT_ESCAPE_CHARACTER,
					CSVWriter.DEFAULT_LINE_END);) {

		// write String Array
		csvWriter.writeNext(CSV_HEADER);

		for(String[] data: datas) {
			csvWriter.writeNext(data);				
		}
		
		System.out.println("Write CSV using CSVWriter successfully!");
	} catch (Exception e) {
		System.out.println("Writing CSV error!");
		e.printStackTrace();
	}
}

The method writeNext is used to write the next line to the file.

Write Object List to CSV File with Position Mapping Strategy

We can combine ColumnPositionMappingStrategy and StatefulBeanToCsv to write object list to csv file.

com.opencsv.bean.StatefulBeanToCsv writes beans out in CSV format to a java.io.Writer, keeping state information and making an intelligent guess at the mapping strategy to be applied.

Now we implement writeCsvFileUsingBeanToCSV method to do the task:

/**
 * Write data to CSV File From List Objects
 */
public static void writeCsvFileUsingBeanToCSV (List customers, String pathFile) {
	try (FileWriter fileWriter = new FileWriter(pathFile);
			CSVWriter csvWriter = new CSVWriter(fileWriter, CSVWriter.DEFAULT_SEPARATOR,
										CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.DEFAULT_ESCAPE_CHARACTER,
										CSVWriter.DEFAULT_LINE_END);) 
	{
		// write Objects List
		ColumnPositionMappingStrategy mappingStrategy = new ColumnPositionMappingStrategy();

		mappingStrategy.setType(Customer.class);
		mappingStrategy.setColumnMapping(CSV_HEADER);

		StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(fileWriter)
															.withMappingStrategy(mappingStrategy)
															.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER).build();

		beanToCsv.write(customers);

		System.out.println("Write CSV using BeanToCsv successfully!");
	} catch (Exception e) {
		System.out.println("Writing CSV error!");
		e.printStackTrace();
	}
}

Using Apache Common to Read CSV file

We use org.apache.commons.csv.CSVParser to parse CSV File according to the specified format.
We have 2 approaches to read CSV File by Apache Common:

  • Parse CSV File using Column Index
  • Parse CSV File using Name Index

Parse CSV File using Column Index

/**
 * Read CSV File by Column Index
 * @param pathfile
 */
public static void parseCSVFileByColumnIndex(String pathfile) {
    try (
    		BufferedReader fileReader = new BufferedReader(new FileReader(pathfile));
			CSVParser csvParser = new CSVParser(fileReader,
					CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase().withTrim());
        ) {
            for (CSVRecord csvRecord : csvParser) {
                // Accessing Values by Column Index
                String id = csvRecord.get(0);
                String name = csvRecord.get(1);
                String email = csvRecord.get(2);
                String salary = csvRecord.get(3);

                System.out.println("Record No - " + csvRecord.getRecordNumber());
                System.out.println("---------------");
                System.out.println("Id : " + id);
                System.out.println("Name : " + name);
                System.out.println("Email : " + email);
                System.out.println("Salary : " + salary);
                System.out.println("---------------\n\n");
            }
        } catch(Exception e) {
        	System.out.println("Reading CSV Error!");
			e.printStackTrace();
        }
}

Run the main class:

public class ReadCSVFileUsingApacheCommon {
	
	public static void main(String[] args) {
		parseCSVFileByColumnIndex("customers.csv");
	}

Output in console:


---------------
Id : 2
Name : Adam
Email : adam@gmail.com
Salary : 2300
---------------


Record No - 3
---------------
Id : 3
Name : Katherin
Email : katherin@gmail.com
Salary : 3000
---------------


Record No - 4
---------------
Id : 4
Name : David
Email : david@gmail.com
Salary : 4200
---------------


Record No - 5
---------------
Id : 5
Name : Jason
Email : jason@gmail.com
Salary : 2500
---------------

Parse CSV File using Name Index

/**
 * Read CSV File using ApacheCommon
 * @param pathfile
 */
public static void readCSVFileByNameIndex(String pathfile) {
	try (
			BufferedReader fileReader = new BufferedReader(new FileReader(pathfile));
			CSVParser csvParser = new CSVParser(fileReader,
					CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase().withTrim());
		)
	{
		List customers = new ArrayList();

		Iterable csvRecords = csvParser.getRecords();

		for (CSVRecord csvRecord : csvRecords) {
			Customer customer = new Customer(Long.parseLong(csvRecord.get("id")), 
												csvRecord.get("name"), csvRecord.get("email"),
														Long.parseLong(csvRecord.get("salary")));

			customers.add(customer);
		}

		for (Customer customer : customers) {
			System.out.println(customer);
		}

	} catch (Exception e) {
		System.out.println("Reading CSV Error!");
		e.printStackTrace();
	}
}

Run run the main class:


public class ReadCSVFileUsingApacheCommon {
	
	public static void main(String[] args) {
		parseCSVFileByNameIndex("customers.csv");
	}

Output in Console:

Customer[id = 1, name = Jack, email = jack@gmail.com, salary = 2000]
Customer[id = 2, name = Adam, email = adam@gmail.com, salary = 2300]
Customer[id = 3, name = Katherin, email = katherin@gmail.com, salary = 3000]
Customer[id = 4, name = David, email = david@gmail.com, salary = 4200]
Customer[id = 5, name = Jason, email = jason@gmail.com, salary = 2500]

Using Apache Common to Write CSV file

It is very simple by using the CSVPrinter to write data to CSV file:

/**
 * Write data list object to CSV File
 */
public static void writeDataToCSVFile(List customers, String pathfile) {
	try (
			FileWriter fileWriter = new FileWriter(pathfile);
			CSVPrinter csvPrinter = new CSVPrinter(fileWriter, CSVFormat.DEFAULT.withHeader(CSV_HEADER)); 
		) 
	{
		for (Customer customer : customers) {
			List data = Arrays.asList(String.valueOf(customer.getId()), customer.getName(), customer.getEmail(),
					String.valueOf(customer.getSalary()));

			csvPrinter.printRecord(data);
		}

		System.out.println("Write CSV successfully!");
	} catch (Exception e) {
		System.out.println("Writing CSV error!");
		e.printStackTrace();
	}
}

Run the main class:

public static void main(String[] args) {
	// prepare customer list
	List customers = Arrays.asList(
									new Customer(1L, "Jack", "jack@gmail.com", 2000L), 
									new Customer(2L, "Adam", "adam@gmail.com", 2300L),
									new Customer(3L, "Katherin", "katherin@gmail.com", 3000L),
									new Customer(4L, "David", "david@gmail.com", 4200L), 
									new Customer(5, "Jason", "jason@gmail.com", 2500L));
	
	writeDataToCSVFile(customers, "customers.csv");
}

Result is a .csv file customers.csv with below content:

result is a csv file
result is a csv file

SourceCode

ReadWriteCsvFile

Leave a Reply

Your email address will not be published. Required fields are marked *