Java 如何使用 servlet 创建 CSV 文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3190303/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 17:15:09  来源:igfitidea点击:

How to create a CSV file using servlet?

javaservletscsv

提问by Rose

I want to download a CSV file from a servlet. I have data in the array of objects (object[]), I need to write it into CSV and download.

我想从servlet下载 CSV 文件。我有对象数组 ( object[]) 中的数据,我需要将其写入 CSV 并下载。

Could you help me how to do this in a servlet class?

你能帮我在 servlet 类中如何做到这一点吗?

回答by NG.

Here's an attempt:

这是一个尝试:

public void doGet(HttpServletRequest request,
                HttpServletResponse response)
  throws ServletException, IOException {

    // Other stuff you know that I don't..

    Object[] data = search.getSearch();
    response.setContentType("text/csv");
    PrintWriter out = response.getWriter();
    for (Object d : data) {
        out.println(d.field1 + "," + d.field2 + "," + d.field3 + ...);
    }
}

This broken if your fields have commas for data. I leave you to figure out how to do that since it's a quick Google Search.

如果您的字段有数据逗号,这会中断。我让你弄清楚如何做到这一点,因为它是一个快速的Google 搜索

回答by Bozho

There is the JavaCSVwhich will help you generate the csv representation.

JavaCSV可以帮助您生成 csv 表示。

Then you can write the file using:

然后您可以使用以下方法编写文件:

  • response.getWriter()to print the contents
  • response.setContentType("text/csv")
  • response.getWriter()打印内容
  • response.setContentType("text/csv")

回答by G__

Here's some (redacted for brevity and generality) code from a production servlet I have running. It should be trivial to swap in your specific data array with the code below.

这是我正在运行的生产 servlet 中的一些(为了简洁和通用而编辑)代码。使用下面的代码交换您的特定数据数组应该很简单。

public void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {

        res.setContentType("application/octet-stream");
        res.setHeader("Content-Disposition", "attachment; filename=\"TSR.csv\"");
        try {
            // Write the header line
            OutputStream o = res.getOutputStream();
            String header = "ID,ControlNumber\n";
            o.write(header.getBytes());

            // Write the data lines
            Vector records = getRecords(); // Custom to my app
            Iterator i = records.iterator();
            while (i.hasNext()) {
                                // Custom data object; use your own
                StandardReportDTO sr = (StandardReportDTO) i.next();
                StringBuffer line = new StringBuffer();
                line.append(sr.getID());
                line.append(",");
                line.append(sr.getControlNumber());
                line.append("\n");
                o.write(line.toString().getBytes());
                o.flush();
            }

        } catch (Exception e) {
//          log.error(e);
        }
}

回答by BalusC

How can Object[]ever represent CSV data? Does it contain one row with several columns or several rows with one column? I'd imagine that Object[][]or List<List<Object>>makes more sense.

如何Object[]表示 CSV 数据?它包含一行多列还是多行一列?我想这Object[][]或者List<List<Object>>更有意义。

Anyway, when creating a CSV file you've to adhere the RFC4180 spec. It's basically simple, there are only 3 strict rules:

无论如何,在创建 CSV 文件时,您必须遵守RFC4180 规范。基本上很简单,只有3条严格的规则:

  1. Fields are separated by a comma.
  2. If a comma occurs within a field, then the field has to be surrounded by double quotes.
  3. If a double quote occurs within a field, then the field has to be surrounded by double quotes and the double quote within the field has to be escaped by another double quote.
  1. 字段以逗号分隔。
  2. 如果字段中出现逗号,则该字段必须用双引号括起来。
  3. 如果一个字段中出现双引号,则该字段必须用双引号括起来,并且该字段中的双引号必须用另一个双引号转义。

Here's a kickoff example which does exactly that based on a List<List<T>>as source and an OutputStreamas destination.

这是一个基于List<List<T>>as 源和OutputStreamas 目标的启动示例。

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();
}

Here's how you can use it in a Servlet:

以下是在 Servlet 中使用它的方法:

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());
}

(note that Europe based locales use a semicolon instead of comma for CSV files, feel free to change)

(请注意,基于欧洲的语言环境对 CSV 文件使用分号而不是逗号,可以随意更改)

The Content-Dispositionof attachmentwill force a Save Asdialogue. Note that MSIE has the misbehaviour that it doesn't take the filenameas default filename in the Save Asdialogue, but it instead takes the last part of the pathinfo. So if this servlet is for example invoked by http://example.com/csv, then you'll get csvas default filename. Rather append it to the pathinfo like follows http://example.com/csv/file.csv. The servlet should only be mapped on an url-patternof /csv/*instead of /csv.

Content-Dispositionattachment将强制另存为对话框。请注意,MSIE 的错误行为是它filename在“另存为”对话框中不采用默认文件名,而是采用路径信息的最后一部分。因此,如果此 servlet 例如由http://example.com/csv调用,那么您将获得csv默认文件名。而是将其附加到 pathinfo ,如下所示http://example.com/csv/file.csv。servlet 应该只映射到url-patternof/csv/*而不是/csv