【问题标题】:Create CSV file without saving it into file system创建 CSV 文件而不将其保存到文件系统中
【发布时间】:2017-06-10 16:50:53
【问题描述】:

我创建了一个 Java 程序来创建一个csv 文件,将数据写入其中,然后将其内容发送到服务器。

在本地,一切正常。但问题是我没有对服务器的写入权限(权限被拒绝问题)。

所以,我不能做任何chmod 777

我正在寻找一种方法来创建csv 文件而不保存到文件系统中。诸如写入流或流之类的东西。我真的不知道它是如何工作的。 请问有什么帮助吗?

这是我到目前为止所做的:

  public void exportAllToCSV(@PathVariable int id,HttpServletResponse response) throws IOException
 String csvFile="test.csv";
 File file = new File("test.csv");
 //some treatments to get datas (headers and values)


  FileWriter writer = new FileWriter(csvFile);
  CsvBuilder.writeLine(writer, headers);
  CsvBuilder.writeLine(writer, values);
  writer.flush();
  writer.close();
  response.setContentType("text/csv");
  response.setHeader("Content-Disposition", "attachment; filename=" + csvFile);
  final BufferedReader br = new BufferedReader(new FileReader(file));

  try {
        String line;

        while ((line = br.readLine()) != null) {
            response.getWriter().write(line + "\n");
        }
    } finally {
        br.close();
    }

    try {
        file.delete(); // I delete the file
    } catch (Exception e) {
        e.printStackTrace();
    }

【问题讨论】:

  • 为什么需要创建文件?为什么不直接将CSV文件写入response.getWriter()
  • 不保存就无法写入文件。 “保存”意味着您写入文件并关闭它。
  • 为什么不在 BufferedReader 中读取文件,将每一行放入 ArrayList 中,然后进行处理?你不会写文件,你会在你的操作内存中工作。不保存就不能“写”,“写”顾名思义就是写入磁盘的方法。
  • @Erwin Bolwidt 我需要创建一个文件来将数据放入其中。
  • @John 为什么?您在请求结束时删除了文件,因此很明显您不需要将其保留在文件中。正如我在第一条评论中所说,您应该将 CSV 文件直接发送到 response.getWriter()

标签: java csv spring-mvc spring-boot inputstream


【解决方案1】:

你可以尝试直接写回复:

Writer writer =  response.getWriter();

CsvBuilder.writeLine(writer, headers);
CsvBuilder.writeLine(writer, values);
writer.flush();
writer.close();

response.setContentType("text/csv");
response.setHeader("Content-Disposition","attachment; filename=" + csvFile);

如果由于某种原因不能使用,并且临时文件也不允许你使用,你可以尝试使用这个非常丑陋的内存变体。

List<Integer> output = new LinkedList<>();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new OutputStream() {
    @Override
    public void write(int b) throws IOException {
        output.add(b);
    }
}));
// write all the things via CsvBuilder
final BufferedReader reader = new BufferedReader(new InputStreamReader(new InputStream() {
    @Override
    public int read() throws IOException {
        if (output.size() > 0) {
            return output.remove(0);
        }
        return -1;
    }
}));

【讨论】:

  • +1 仅适用于第一部分。第二部分是一个坏主意并且完全被破坏了,因为它从写入的内容中反向读取数据。您应该为此使用 StringWriter 和 StringReader。
  • @ErwinBolwidt 谢谢你,修正了订单,你是对的:正如我所说的第二个是坏的和丑陋的
  • 几乎。我认为你是对的我试图直接写响应,但我的浏览器中只有 csv 文件的内容。像 .txt 我没有 csv 文件。有什么想法吗?
  • 谢谢它真的很有帮助!
【解决方案2】:

假设CsvBuilder.writeLine(...) 只接受java.io.Writer 的实例,为什么不使用java.io.StringWriterjava.util.Scanner

// ...

StringWriter writer = new StringWriter();
CsvBuilder.writeLine(writer, headers);
CsvBuilder.writeLine(writer, values);
writer.flush();

response.setContentType("text/csv");
response.setHeader("Content-Disposition", "attachment; filename=test.csv");

Scanner scanner = new Scanner(new StringReader(writer.toString()))
while (scanner.hasNext()) {
   response.getWriter().write(scanner.next() + "\n");
}

// ...

但是,我认为 Andrei Makarevich 直接使用response.getWriter() 的答案可能是最前卫的方法。虽然,我不确定CsvBuilder 是否会添加换行符,因为您明确添加了它们!?

【讨论】:

  • 差不多好了!我得到了 csv,但有一个问题:当句子中有空格时,空格后面的单词会出现在下一行。你能解释一下scanner.hasNext() 部分吗?
  • scanner.hasNext() 检查是否存在另一行,scanner.next() 获取该行。不知道为什么句子中有空格时会出现换行。
  • 有效!我直接尝试过: response.getWriter().write(writer.toString() + "\n");谢谢
【解决方案3】:

如果允许临时文件,你可以试试:

File temp = File.createTempFile("test.csv", ".csv");

这些文件是在系统的用户存储中创建的,例如 Windows 中的“C:\Users[Username]\AppData”,或类似的东西。我不知道确切的路径,但现在应该不重要了。

查看Java中存在的所有类型的OutputStreams,不仅仅是FileOutputStream: https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html 检查子类。

【讨论】:

    【解决方案4】:

    您可以使用 StringBuilderWriter 来拥有一个 writer 而不是 FileWriter

    final Writer writer = new StringBuilderWriter();
    

    【讨论】:

    • Apache Commons StringBuilderWriter?在多线程环境中要小心。
    【解决方案5】:

    如果有人还在寻找答案,下面的代码对我来说非常有用

    导入以下依赖项

        <dependency>
            <groupId>net.sourceforge.javacsv</groupId>
            <artifactId>javacsv</artifactId>
            <version>2.0</version>
        </dependency>
    

    以下代码,我将数据写入 ByteArrayOutputStream,而不是 FileWriter

      ByteArrayOutputStream out = new ByteArrayOutputStream();
      CsvWriter csvWriter = new CsvWriter(new BufferedOutputStream(out), ',', Charset.forName("UTF-8"));
      String[] data = new String[] { "fieldValueA", "fieldValueB", "fieldValueC" };
      csvWriter.writeRecord(data);
      csvWriter.close();
    

    【讨论】:

    • 数据是List怎么样?
    猜你喜欢
    • 2013-08-19
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多