Как Object[]
может представлять данные CSV?Содержит ли он одну строку с несколькими столбцами или несколько строк с одним столбцом?Я думаю, что Object[][]
или List<List<Object>>
имеет больше смысла.
В любом случае, при создании файла CSV вы должны придерживаться RFC4180 spec .Это в основном просто, есть только 3 строгих правила:
- Поля разделены запятой.
- Если запятая встречается внутри поля, то поле должно быть окружено двойнымкавычки.
- Если в поле встречается двойная кавычка, то поле должно быть окружено двойными кавычками, а двойная кавычка внутри поля должна быть экранирована другой двойной кавычкой.
Вот пример запуска, который делает именно это на основе List<List<T>>
в качестве источника и OutputStream
в качестве пункта назначения.
public static <T> void writeCsv (List<List<T>> csv, char separator, OutputStream output) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, "UTF-8"));
for (List<T> row : csv) {
for (Iterator<T> iter = row.iterator(); iter.hasNext();) {
String field = String.valueOf(iter.next()).replace("\"", "\"\"");
if (field.indexOf(separator) > -1 || field.indexOf('"') > -1) {
field = '"' + field + '"';
}
writer.append(field);
if (iter.hasNext()) {
writer.append(separator);
}
}
writer.newLine();
}
writer.flush();
}
Вот как вы можете использовать его в сервлете:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<List<Object>> csv = getItSomehow();
response.setHeader("Content-Type", "text/csv");
response.setHeader("Content-Disposition", "attachment;filename=\"file.csv\"");
writeCsv(csv, ';', response.getOutputStream());
}
(обратите внимание, что европейские локали используют точку с запятой вместо CSV для файлов CSV, не стесняйтесь менять)
Content-Disposition
из attachment
приведет к Сохранить как диалог.Обратите внимание, что у MSIE неправильное поведение: он не принимает filename
в качестве имени файла по умолчанию в диалоге Сохранить как , но вместо этого использует последнюю часть pathinfo.Так, если этот сервлет, например, вызывается http://example.com/csv,, тогда вы получите csv
в качестве имени файла по умолчанию.Вместо этого добавьте его в pathinfo следующим образом http://example.com/csv/file.csv. Сервлет должен отображаться только на url-pattern
из /csv/*
вместо /csv
.