Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create CSV file without saving it into file system

I've created a Java program to create a csv file, write data into it and then send its contents to the server.

Locally, everything works fine. But the problem is that I don't have write access to the server (permission denied problem).

So, I can't do any chmod 777.

I'm looking for a way to create a csv file without saving into the file system. Something like write into a flow or a stream. I don't really know how it works. Any help please ?

This was what I have done so far:

  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();
    }
like image 826
John Avatar asked Feb 06 '23 06:02

John


2 Answers

You can try to write directly to response:

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

If that can not be used for some reason and temporary files are also not allowed for you, you can try to use this pretty ugly in-memory variant.

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;
    }
}));
like image 138
Andrei Makarevich Avatar answered Feb 07 '23 20:02

Andrei Makarevich


Assuming that CsvBuilder.writeLine(...) does only accept an instance of java.io.Writer, why not using java.io.StringWriter and java.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");
}

// ...

However, I think Andrei Makarevich's answer using response.getWriter() directly is probably the most forward approach. Although, I'm not sure if the line feeds will be added by CsvBuilder since your adding them explicitly!?

like image 21
Thomas Avatar answered Feb 07 '23 19:02

Thomas