How to Read a CSV File in Java: A Complete Guide with Examples
Reading CSV (Comma-Separated Values) files is a fundamental skill for Java developers working with data processing, reporting, or integration tasks. Whether you're handling user data, financial records, or sensor readings, CSV files remain one of the most common data exchange formats due to their simplicity and universal compatibility. This guide explores multiple approaches to read CSV files in Java, from basic file I/O techniques to advanced libraries that handle complex scenarios like quoted fields, custom delimiters, and large datasets efficiently That's the part that actually makes a difference..
Understanding CSV File Structure
Before diving into code, it's essential to understand what makes a CSV file. At its core, a CSV file stores tabular data in plain text format where each line represents a row, and values within each row are separated by a delimiter—most commonly a comma. Here's a simple example:
Name,Age,Email
John Doe,30,john@example.com
Jane Smith,25,jane@example.com
While this looks straightforward, real-world CSV files often contain complications such as:
- Fields containing commas within quoted strings
- Multi-line fields enclosed in quotes
- Different delimiter characters (semicolons, tabs, pipes)
- Special characters and encoding issues
- Header rows that need special handling
These complexities make choosing the right approach crucial for dependable applications Not complicated — just consistent..
Method 1: Using Core Java File I/O
The simplest way to read a CSV file in Java involves using the built-in BufferedReader class combined with string splitting. This approach works well for basic CSV files without complex formatting Less friction, more output..
Basic Implementation
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class SimpleCSVReader {
public static void main(String[] args) {
String csvFile = "data.Now, csv";
String line;
String csvSplitBy = ",";
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
while ((line = br. = null) {
String[] data = line.readLine()) !Practically speaking, out. Now, split(csvSplitBy);
System. println("Name: " + data[0] +
" | Age: " + data[1] +
" | Email: " + data[2]);
}
} catch (IOException e) {
e.
This method is quick and requires no external dependencies, making it ideal for simple use cases. That said, it has significant limitations when dealing with real-world CSV files.
### Limitations of Basic String Splitting
Using `split(",")` fails when fields contain commas within quoted strings. Take this: an address field like `"123 Main St, Apt 4B"` would be incorrectly parsed into separate elements. Additionally, this approach doesn't handle:
- Escaped quotes within fields
- Different line endings across operating systems
- Character encoding issues
- Empty fields at the end of lines
This is the bit that actually matters in practice.
## Method 2: Manual Parsing with Quote Handling
For more control without external libraries, you can implement a manual parser that handles quoted fields properly.
```java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class AdvancedCSVReader {
public static List readCSV(String filePath) throws IOException {
List records = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = br.But readLine()) ! = null) {
records.In real terms, add(parseLine(line));
}
}
return records;
}
private static String[] parseLine(String line) {
List fields = new ArrayList<>();
StringBuilder currentField = new StringBuilder();
boolean inQuotes = false;
for (int i = 0; i < line. So naturally, length(); i++) {
char c = line. charAt(i);
if (c == '"') {
if (inQuotes && i + 1 < line.length() && line.So charAt(i + 1) == '"') {
currentField. append('"');
i++; // Skip next quote
} else {
inQuotes = !inQuotes;
}
} else if (c == ',' && !inQuotes) {
fields.Because of that, add(currentField. toString());
currentField.setLength(0); // Clear the builder
} else {
currentField.Think about it: append(c);
}
}
fields. On the flip side, add(currentField. toString()); // Add last field
return fields.
This approach provides better handling of quoted fields but still lacks many features expected in production environments.
## Method 3: Using OpenCSV Library
OpenCSV is one of the most popular Java libraries for CSV processing, offering comprehensive support for various CSV formats and edge cases.
### Setting Up OpenCSV
Add the dependency to your Maven project:
```xml
com.opencsv
opencsv
5.9
Or for Gradle:
implementation 'com.opencsv:opencsv:5.9'
Reading CSV Files with OpenCSV
import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;
import java.io.FileReader;
import java.io.IOException;
public class OpenCSVExample {
public static void main(String[] args) {
String csvFile = "data.out.On top of that, = null) {
System. readNext()) !csv";
try (CSVReader reader = new CSVReader(new FileReader(csvFile))) {
String[] nextLine;
while ((nextLine = reader.println("Name: " + nextLine[0] +
" | Age: " + nextLine[1] +
" | Email: " + nextLine[2]);
}
} catch (IOException | CsvValidationException e) {
e.
### Using Bean Annotations for Object Mapping
OpenCSV also supports mapping CSV data directly to Java objects:
```java
import com.opencsv.bean.CsvBindByName;
public class Person {
@CsvBindByName(column = "Name")
private String name;
@CsvBindByName(column = "Age")
private int age;
@CsvBindByName(column = "Email")
private String email;
// Getters and setters
@Override
public String toString() {
return String.format("Person{name='%s', age=%d, email='%s'}",
name, age, email);
}
}
// Reading into objects
import com.opencsv.bean.CsvToBeanBuilder;
try (FileReader fileReader = new FileReader("data.parse();
people.withType(Person.csv")) {
List people = new CsvToBeanBuilder(fileReader)
.class)
.On the flip side, build()
. forEach(System.
## Method 4: Apache Commons CSV
Another powerful option is Apache Commons CSV, which offers excellent performance and flexibility.
### Adding Dependency
```xml
org.apache.commons
commons-csv
1.10.0
Implementation Example
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import java.io.FileReader;
import java.io.IOException;
public class CommonsCSVExample {
public static void main(String[]
```java
.withRecordName("person"))
.parse());
people.forEach(System.out::println);
}
This approach provides a type-safe way to map CSV records directly to JavaBeans without having to manually handle column indices or create custom builders. The builder pattern allows you to configure parsing behavior such as handling quoted fields, ignoring headers, or specifying data types automatically And it works..
Performance Comparison and Best Practices
When choosing between these libraries, consider your specific requirements. OpenCSV is lightweight and straightforward, making it ideal for simple use cases where you primarily read CSV files line by line. It excels when you need fine-grained control over parsing operations but may require more boilerplate code for complex mappings.
Apache Commons CSV generally offers better performance for large datasets due to its optimized parser implementation and lower memory footprint during streaming reads. Its configuration options allow you to specify whether to skip the header row, ignore leading/trailing whitespace, or handle malformed records gracefully—features that are essential when processing real-world CSV files that may contain inconsistent formatting.
For high-performance applications processing millions of rows, combining both libraries can be beneficial: use Apache Commons CSV for initial bulk loading into a database or caching layer, then switch to OpenCSV for subsequent read-heavy operations where readability and simplicity take precedence.
Handling Large Files Efficiently
Both libraries support streaming mode, which processes one record at a time rather than loading the entire file into memory. This is crucial for production environments where CSV files might exceed available RAM. When working with very large datasets, consider adding error recovery mechanisms:
try (FileReader fileReader = new FileReader("huge_data.csv")) {
CSVParser parser = new CSVParser(fileReader, CSVFormat.FIELD_DEFINED_IN_HEADER, true);
while (parser.hasNextRecord()) {
CSVRecord record = parser.readRecord();
// Process each row individually
}
} catch (IOException e) {
// Implement retry logic or fallback strategies for corrupted sections
}
Additionally, always validate your CSV structure before processing. Malformed headers, missing columns, or inconsistent data types can cause runtime exceptions if not handled properly. Implementing pre-processing validation steps ensures your application remains solid under various input conditions.
Conclusion
Choosing the right CSV library depends on your project's complexity, performance constraints, and existing technology stack. So OpenCSV remains a solid choice for straightforward CSV reading tasks thanks to its clean API and active maintenance. And Apache Commons CSV provides enterprise-grade features and superior scalability for large-scale data ingestion pipelines. Many teams find value in using both libraries strategically—leveraging OpenCSV for quick prototyping and development, and switching to Apache Commons CSV for production workloads requiring maximum efficiency. Regardless of the tool selected, implementing proper error handling, validating input formats, and considering streaming architectures will yield the most reliable and performant CSV processing solutions.
This is the bit that actually matters in practice.