Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to write a CSV file

Short answer

Build the lines with String.join() and write them with Files.write():

record Product(String name, double price) {}
 
void main() throws IOException {
    var products = List.of(new Product("Tea", 3.5), new Product("Cake", 12.0));
 
    var lines = new ArrayList<String>();
    lines.add("name,price");
    for (Product p : products) {
        lines.add(String.join(",", p.name(), String.valueOf(p.price())));
    }
    Files.write(Path.of("products.csv"), lines);
 
    IO.print(Files.readString(Path.of("products.csv")));
}

Output:

name,price
Tea,3.5
Cake,12.0

Escaping

A value with a comma, a quote or a line break is wrapped in quotes, and quotes inside are doubled:

String csv(String value) {
    if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
        return "\"" + value.replace("\"", "\"\"") + "\"";
    }
    return value;
}
 
void main() {
    IO.println(csv("Tea"));
    IO.println(csv("Smith, John"));
    IO.println(csv("The \"Best\" cake"));
}

Output:

Tea
"Smith, John"
"The ""Best"" cake"

With a stream

Lines are easy to build with a stream:

void main() throws IOException {
    var rows = List.of(List.of("Anna", "30"), List.of("Oleg", "25"));
    var lines = rows.stream().map(row -> String.join(",", row)).toList();
 
    Files.write(Path.of("people.csv"), lines);
    IO.println(Files.readAllLines(Path.of("people.csv")));
}

Output:

[Anna,30, Oleg,25]

Common mistake

Writing decimals with String.format("%.2f") without a locale. On a computer with a German or Russian locale you get 3,50, and the comma splits the value into two cells. Use String.valueOf() or String.format(Locale.ROOT, "%.2f", value).

Functions used in this recipe

Thanks for reading!

Donate to the site — we work hard for you.