CSV Parser with Quoted Fields
Problem
Split every CSV line into fields. A comma separates fields, except inside double quotes. A field in double quotes can contain commas, and two double quotes in a row mean one quote character. The surrounding quotes are not part of the field. Print the fields of each line joined by the | character.
Constraints
- 1 <= lines <= 10^4
Examples
Input
a,b,c "hello, world",x
Output
a|b|c hello, world|x
Solutions
Splitting on commas is not enough for real CSV files. A small state machine that remembers whether we are inside quotes handles commas and doubled quotes. In real projects use a tested CSV library.
/*
* Problem : Process lines.
* Input : Several lines.
* Output : Fields joined by |.
* Approach: CSV lines.
* Time : O(total length)
* Space : O(line length)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: Split one line with a small state machine. "inQuotes" tells if we are inside a quoted field.
static String parseLine(String line) {
java.util.List<String> fields = new java.util.ArrayList<>();
StringBuilder current = new StringBuilder();
boolean inQuotes = false;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (inQuotes) {
// Step 2: Inside quotes, two quotes in a row mean one quote. A single quote ends the field text.
if (c == '"' && i + 1 < line.length() && line.charAt(i + 1) == '"') {
current.append('"');
i++;
} else if (c == '"') {
inQuotes = false;
} else {
current.append(c);
}
} else if (c == '"') {
inQuotes = true;
} else if (c == ',') {
// Step 3: A comma outside quotes ends the field.
fields.add(current.toString());
current.setLength(0);
} else {
current.append(c);
}
}
fields.add(current.toString());
return String.join("|", fields);
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
output[i] = parseLine(lines[i]);
}
return output;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
all.add(scanner.nextLine());
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (1)
- Why does line.split(',') fail on quoted fields?