创建 CSV 文件而不将其保存到文件系统中

Create CSV file without saving it into file system

我创建了一个 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();
    }

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

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 检查子类。

您可以尝试直接写回复:

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

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

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

假设 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 是否会添加换行符,因为你明确地添加了它们!?

您可以使用 StringBuilderWriter 代替 FileWriter 来编写程序

final Writer writer = new StringBuilderWriter();

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

导入以下依赖项

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