Как записать CSV-файл
Короткий ответ
Соберите строки через String.join() и запишите их через 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")));
}Результат:
name,price
Tea,3.5
Cake,12.0Экранирование
Значение с запятой, кавычкой или переводом строки берут в кавычки, а кавычки внутри удваивают:
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"));
}Результат:
Tea
"Smith, John"
"The ""Best"" cake"Через поток
Строки удобно строить потоком:
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")));
}Результат:
[Anna,30, Oleg,25]Частая ошибка
Записывать дробные числа через String.format("%.2f") без локали. На компьютере с немецкой или русской локалью получится 3,50, и запятая разобьёт значение на две ячейки. Используйте String.valueOf() или String.format(Locale.ROOT, "%.2f", value).
Функции из этого ответа
- Files.writeString() — Записывает строку в файл: создаёт его или перезаписывает.
- Collectors.joining() — Сборщик, который склеивает строки потока в одну.
- String.replace() — Заменяет все вхождения подстроки или символа на другую строку.