Create CSV file without saving it into file system
Solution 1
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!?
Solution 2
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;
}
}));
Solution 3
You can try, if temporary files are allowed:
File temp = File.createTempFile("test.csv", ".csv");
These files are getting created in the user storage of the system, so like "C:\Users[Username]\AppData" in Windows, or something like that. I don't know the exact path, but that should not be important now.
Check out all the kinds of OutputStreams, that exist in Java, there is more than the FileOutputStream: https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html Check the subclasses.
John
Updated on June 05, 2022Comments
-
John almost 2 years
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(); }
-
Erwin Bolwidt over 7 yearsWhy do you need to create a file? Why don't you write the CSV file directly to
response.getWriter()
? -
rajah9 over 7 yearsYou can't write the file without saving it. "Save" means you write the file and close it.
-
Amnor over 7 yearsWhy don't you read the file in a BufferedReader, put everyline in an ArrayList, and then work on that? you wouldn't write a file, and you would be working in your operating memory. You can't "write" without saving, "write" is a method that, as its name says, writes to disk.
-
John over 7 years@Erwin Bolwidt I need to create a file to put data in it.
-
Erwin Bolwidt over 7 years@John Why ? You are deleting the file at the end of the request so clearly you don't need to leave it in the file. As I said in my first comment, you should send the CSV file directly to
response.getWriter()
-
John about 7 yearsYou're right ! I have writen directly in the response. I didn't know it was possible . Many Thanks
-
-
Thomas over 7 yearsApache Commons
StringBuilderWriter
? Be careful within a multi threaded environment. -
Erwin Bolwidt over 7 years+1 only for the first part. The second part is a bad idea and totally broken since it reads the data back in reverse from what was written. You should just use a StringWriter and a StringReader for that.
-
Andrei Makarevich over 7 years@ErwinBolwidt thank you, fixed the order, and you are right: as I told the second one is bad and ugly
-
John over 7 yearsAlmost . I think you 're right I tried to write directly the response but I have only the content of the csv file in my browser. Like a .txt I don't get a csv file. Any idea ?
-
John over 7 yearsAlmost good ! I got the csv but one problem : When there is a space in a sentence, the word after space comes in the next line.. Could you please explain scanner.hasNext() part ?
-
Thomas over 7 years
scanner.hasNext()
checks if another line exists andscanner.next()
gets that line. Don't know why you get a line feed when there is a space within a sentence. -
John over 7 yearsIt works ! I have tried directly : response.getWriter().write(writer.toString() + "\n"); Thank you
-
John over 7 yearsThanks it was really helpful !
-
Hanh Nguyen over 2 yearsHow about the data is List<Map, String>?