Q&A
How to parse a CSV file in Java
Overview
CSV ("comma-separated values") looks simple but has subtle rules: fields may be quoted, quoted fields may contain commas or newlines, and quotes inside fields are escaped by doubling. A naive split(",") ignores all of this. For anything beyond toy data, use a library that implements the CSV format (RFC 4180) correctly.
graph TD
A[Parse CSV] --> B[Trivial, no quotes/commas-in-fields]
A --> C[Real-world CSV]
B --> B1[BufferedReader + split(',')]
C --> C1[Apache Commons CSV]
C --> C2[OpenCSV]
style C1 fill:#1e1b4b,color:#fff
style C2 fill:#1e1b4b,color:#fff
Approach 1: BufferedReader + split (simple files only)
import java.io.*;
import java.nio.file.*;
try (BufferedReader br = Files.newBufferedReader(Paths.get("data.csv"))) {
String line;
boolean header = true;
while ((line = br.readLine()) != null) {
if (header) { header = false; continue; } // skip header row
String[] fields = line.split(",", -1); // -1 keeps trailing empties
String name = fields[0];
String email = fields[1];
// ...
}
}
This works only if no field contains a comma, quote, or newline. The -1 limit to split preserves trailing empty fields (otherwise they're dropped). Convenient but fragile.
Why split(",") Fails on Real CSV
"Smith, John","john@x.com","Says ""hi"""
A single record where the first field contains a comma and the third contains escaped quotes. split(",") would wrongly break "Smith and John" into two fields. Correct parsing requires honoring quotes - exactly what libraries do.
Approach 2: Apache Commons CSV (recommended)
import org.apache.commons.csv.*;
import java.io.*;
import java.nio.file.*;
try (Reader reader = Files.newBufferedReader(Paths.get("data.csv"));
CSVParser parser = CSVParser.parse(reader,
CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true).build())) {
for (CSVRecord record : parser) {
String name = record.get("name"); // access by header name
String email = record.get("email");
// or by index: record.get(0)
}
}
It handles quoted fields, embedded commas/newlines, escaped quotes, and header-based access automatically.
Approach 3: OpenCSV
import com.opencsv.CSVReader;
import java.io.*;
try (CSVReader reader = new CSVReader(new FileReader("data.csv"))) {
String[] row;
reader.readNext(); // skip header
while ((row = reader.readNext()) != null) {
String name = row[0];
// ...
}
}
OpenCSV also supports bean mapping - binding rows directly to Java objects via annotations:
List<Person> people = new CsvToBeanBuilder<Person>(reader)
.withType(Person.class).build().parse();
Choosing an Approach
split(",")- only for throwaway scripts on data you fully control (no quotes/commas in fields).- Apache Commons CSV - robust, header access, great general choice.
- OpenCSV - robust, plus convenient bean (object) mapping.
Practical Considerations
- Encoding - specify charset (e.g. UTF-8) when reading; watch for a BOM.
- Headers - use header-aware parsing to access fields by name (resilient to column reordering).
- Large files - stream record-by-record (as above) rather than loading everything into memory.
- Delimiters - real "CSV" files sometimes use
;or tabs; configure the format accordingly.
Why This Matters in Interviews
This tests file I/O and awareness of real-world data messiness. The key insight interviewers want: split(",") is wrong for general CSV because it can't handle quoted fields containing commas, newlines, or escaped quotes - so use Apache Commons CSV or OpenCSV. Demonstrating try-with-resources for the reader, header-based access, streaming for large files, and encoding awareness signals production experience.
Common Pitfalls
- Using
split(",")and breaking on quoted fields with embedded commas/newlines. split(",")dropping trailing empty fields (pass-1as the limit).- Not skipping the header row, or hard-coding column indices that shift.
- Ignoring character encoding (mojibake / BOM issues).
- Loading a huge file fully into memory instead of streaming records.
References
- Apache Commons CSV: https://commons.apache.org/proper/commons-csv/
- OpenCSV: https://opencsv.sourceforge.net/