DEV Community

Sadiul Hakim
Sadiul Hakim

Posted on

Comprehensive CSV File Handling in Java Tutorial

This tutorial covers CSV file handling using both raw Java and the OpenCSV library.

1. Using Raw Java

Reading CSV Files with Raw Java

import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class RawJavaCSVReader { public static void main(String[] args) { String csvFile = "data.csv"; String line = ""; String csvDelimiter = ","; // CSV files typically use comma as delimiter List<String[]> data = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) { // Read the header line (first line) String headerLine = br.readLine(); if (headerLine != null) { String[] headers = headerLine.split(csvDelimiter); System.out.println("Headers: " + String.join(", ", headers)); } // Read data lines while ((line = br.readLine()) != null) { // Split the line by comma, handling quoted fields String[] values = parseCSVLine(line, csvDelimiter); data.add(values); // Print the row System.out.println("Row: " + String.join(" | ", values)); } } catch (IOException e) { e.printStackTrace(); } System.out.println("Total rows read: " + data.size()); } /** * Parses a CSV line, handling quoted fields that may contain commas * @param line the CSV line to parse * @param delimiter the delimiter character * @return array of field values */ private static String[] parseCSVLine(String line, String delimiter) { List<String> values = new ArrayList<>(); StringBuilder currentValue = new StringBuilder(); boolean inQuotes = false; for (int i = 0; i < line.length(); i++) { char c = line.charAt(i); if (c == '"') { // Handle quotes - either start/end of quoted field or escaped quote if (inQuotes && i < line.length() - 1 && line.charAt(i + 1) == '"') { // Escaped quote inside quoted field currentValue.append('"'); i++; // Skip the next quote } else { // Toggle quote state inQuotes = !inQuotes; } } else if (c == delimiter.charAt(0) && !inQuotes) { // Found delimiter outside quotes - end of field values.add(currentValue.toString()); currentValue = new StringBuilder(); } else { // Regular character currentValue.append(c); } } // Add the last field values.add(currentValue.toString()); return values.toArray(new String[0]); } } 
Enter fullscreen mode Exit fullscreen mode

Writing CSV Files with Raw Java

import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; import java.util.List; public class RawJavaCSVWriter { public static void main(String[] args) { String csvFile = "output.csv"; // Sample data List<String[]> data = Arrays.asList( new String[]{"Name", "Age", "City", "Email"}, new String[]{"John Doe", "30", "New York", "john@example.com"}, new String[]{"Jane Smith", "25", "London", "jane@example.com"}, new String[]{"Bob Johnson", "35", "Paris", "bob@example.com"} ); try (BufferedWriter bw = new BufferedWriter(new FileWriter(csvFile))) { for (String[] row : data) { // Format each row as CSV String csvLine = formatAsCSV(row); bw.write(csvLine); bw.newLine(); } System.out.println("CSV file written successfully: " + csvFile); } catch (IOException e) { e.printStackTrace(); } } /** * Formats an array of values as a CSV line * @param values array of field values * @return CSV formatted string */ private static String formatAsCSV(String[] values) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < values.length; i++) { String value = values[i]; // Check if value needs quoting (contains comma, quote, or newline) boolean needsQuotes = value.contains(",") || value.contains("\"") || value.contains("\n"); if (needsQuotes) { sb.append('"'); // Escape quotes by doubling them sb.append(value.replace("\"", "\"\"")); sb.append('"'); } else { sb.append(value); } // Add delimiter unless it's the last value if (i < values.length - 1) { sb.append(','); } } return sb.toString(); } } 
Enter fullscreen mode Exit fullscreen mode

2. Using OpenCSV

Setting Up OpenCSV

Add OpenCSV dependency to your project:

Maven:

<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.7.1</version> </dependency> 
Enter fullscreen mode Exit fullscreen mode

Gradle:

implementation 'com.opencsv:opencsv:5.7.1' 
Enter fullscreen mode Exit fullscreen mode

Reading CSV Files with OpenCSV

import com.opencsv.CSVReader; import com.opencsv.CSVReaderBuilder; import com.opencsv.exceptions.CsvException; import java.io.FileReader; import java.io.IOException; import java.util.List; public class OpenCSVReaderExample { public static void main(String[] args) { String csvFile = "data.csv"; try (CSVReader reader = new CSVReaderBuilder(new FileReader(csvFile)) .withSkipLines(0) // Skip lines if needed (e.g., skip header) .build()) { // Read all records at once List<String[]> allData = reader.readAll(); // Process each record for (int i = 0; i < allData.size(); i++) { String[] row = allData.get(i); if (i == 0) { System.out.println("Headers: " + String.join(", ", row)); } else { System.out.println("Row " + i + ": " + String.join(" | ", row)); } } System.out.println("Total records: " + allData.size()); } catch (IOException | CsvException e) { e.printStackTrace(); } } } 
Enter fullscreen mode Exit fullscreen mode

Reading CSV with Custom Settings

import com.opencsv.CSVReader; import com.opencsv.CSVReaderBuilder; import com.opencsv.exceptions.CsvException; import java.io.FileReader; import java.io.IOException; import java.util.List; public class OpenCSVAdvancedReader { public static void main(String[] args) { String csvFile = "data.csv"; try (CSVReader reader = new CSVReaderBuilder(new FileReader(csvFile)) .withCSVParser(new com.opencsv.CSVParserBuilder() .withSeparator(',') // Set custom separator .withQuoteChar('"') // Set custom quote character .withEscapeChar('\\') // Set escape character .build()) .withSkipLines(1) // Skip header line .build()) { // Read line by line (better for large files) String[] nextLine; int rowCount = 0; while ((nextLine = reader.readNext()) != null) { rowCount++; System.out.println("Row " + rowCount + ": " + String.join(" | ", nextLine)); // Process individual fields for (int i = 0; i < nextLine.length; i++) { System.out.println(" Field " + i + ": " + nextLine[i]); } } System.out.println("Total rows processed: " + rowCount); } catch (IOException | CsvException e) { e.printStackTrace(); } } } 
Enter fullscreen mode Exit fullscreen mode

Writing CSV Files with OpenCSV

import com.opencsv.CSVWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; import java.util.List; public class OpenCSVWriterExample { public static void main(String[] args) { String csvFile = "output.csv"; // Sample data List<String[]> data = Arrays.asList( new String[]{"Name", "Age", "City", "Email"}, new String[]{"John Doe", "30", "New York", "john@example.com"}, new String[]{"Jane Smith", "25", "London", "jane@example.com"}, new String[]{"Bob Johnson", "35", "Paris", "bob@example.com"} ); try (CSVWriter writer = new CSVWriter(new FileWriter(csvFile))) { // Write all records at once writer.writeAll(data); System.out.println("CSV file written successfully: " + csvFile); } catch (IOException e) { e.printStackTrace(); } } } 
Enter fullscreen mode Exit fullscreen mode

Writing CSV with Custom Settings

import com.opencsv.CSVWriter; import com.opencsv.ICSVWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; public class OpenCSVAdvancedWriter { public static void main(String[] args) { String csvFile = "output_custom.csv"; try (CSVWriter writer = new CSVWriter( new FileWriter(csvFile), ';', // Custom separator (semicolon instead of comma) ICSVWriter.DEFAULT_QUOTE_CHARACTER, ICSVWriter.DEFAULT_ESCAPE_CHARACTER, ICSVWriter.DEFAULT_LINE_END)) { // Write header writer.writeNext(new String[]{"ID", "Product", "Price", "Description"}); // Write data rows writer.writeNext(new String[]{"1", "Laptop", "999.99", "High-performance laptop"}); writer.writeNext(new String[]{"2", "Mouse", "25.50", "Wireless optical mouse"}); writer.writeNext(new String[]{"3", "Keyboard", "75.00", "Mechanical gaming keyboard"}); // Write a row with special characters that need quoting writer.writeNext(new String[]{"4", "Monitor, 24\"", "200.00", "24-inch monitor, with stand"}); System.out.println("Custom CSV file written successfully: " + csvFile); } catch (IOException e) { e.printStackTrace(); } } } 
Enter fullscreen mode Exit fullscreen mode

Mapping CSV to Java Objects with OpenCSV

import com.opencsv.bean.CsvToBean; import com.opencsv.bean.CsvToBeanBuilder; import com.opencsv.bean.HeaderColumnNameMappingStrategy; import java.io.FileReader; import java.io.IOException; import java.util.List; // Define a Java bean class that matches CSV structure class Person { private String name; private int age; private String city; private String email; // Default constructor required by OpenCSV public Person() {} // Parameterized constructor public Person(String name, int age, String city, String email) { this.name = name; this.age = age; this.city = city; this.email = email; } // Getters and setters (required by OpenCSV) public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + ", city='" + city + "', email='" + email + "'}"; } } public class OpenCSVBeanExample { public static void main(String[] args) { String csvFile = "people.csv"; try (FileReader reader = new FileReader(csvFile)) { // Create mapping strategy HeaderColumnNameMappingStrategy<Person> strategy = new HeaderColumnNameMappingStrategy<>(); strategy.setType(Person.class); // Create CSV to bean converter CsvToBean<Person> csvToBean = new CsvToBeanBuilder<Person>(reader) .withMappingStrategy(strategy) .withIgnoreLeadingWhiteSpace(true) .build(); // Convert CSV to list of Person objects List<Person> people = csvToBean.parse(); // Process the objects for (Person person : people) { System.out.println(person); // You can now work with Person objects instead of raw arrays if (person.getAge() > 30) { System.out.println(" -> Over 30 years old"); } } } catch (IOException e) { e.printStackTrace(); } } } 
Enter fullscreen mode Exit fullscreen mode

Comparison: Raw Java vs OpenCSV

Raw Java Advantages:

  • No external dependencies
  • Full control over parsing logic
  • Good for simple CSV files

Raw Java Disadvantages:

  • Complex to handle edge cases (quoted fields, escaped characters)
  • More code to write and maintain
  • No built-in support for data mapping

OpenCSV Advantages:

  • Handles all CSV edge cases automatically
  • Easy to use API
  • Support for mapping CSV to Java objects
  • Better performance for large files
  • Built-in support for different formats and encodings

OpenCSV Disadvantages:

  • External dependency
  • Less control over low-level parsing

Best Practices

  1. Always handle exceptions properly - CSV files can have various formatting issues
  2. Use try-with-resources to ensure files are properly closed
  3. Validate data - check for null values and data types
  4. Consider file encoding - specify UTF-8 if working with international characters
  5. Use OpenCSV for production code - it handles edge cases better than custom code
  6. For large files, read line by line instead of loading entire file into memory

Top comments (0)