I implemented an OutputWriterService.class
to write content in the same file multiple times.
The writeToCsvFile
method is called round about 50.000 times and includes a list of descrptions which also needs to iterate and write to the file.
Is it a good way to instantiate a new Filewriter
, BufferedWriter
and PrintWriter
for every call?
public void writeToCsvFile(List<CustomTypeDescription> descriptions){
try(FileWriter fw = new FileWriter(FILE_NAME, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter out = new PrintWriter(bw))
{
for(CustomTypeDescription description : descriptions){
out.println(description.toString());
}
//here the fw.flush()?
} catch (IOException e) {
e.printStackTrace();
}
}
public void createOutputFile() throws IOException {
try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(FILE_NAME), "utf-8"))) {
}
}
Update:
Is it necessary to flush File
-, Buffered
- and Print
writer one by one or just the FileWriter
. I would do it after the loop?
-
\$\begingroup\$ stackoverflow.com/a/27048070/648075 ? \$\endgroup\$BCdotWEB– BCdotWEB2016年04月20日 08:38:04 +00:00Commented Apr 20, 2016 at 8:38
-
\$\begingroup\$ @BCdotWEB the answer mentioned to flush the FileWriter. Is it necessary to flush File, Buffered and Printwriter one by one or just the FileWriter. I would do it after the loop? \$\endgroup\$Patrick– Patrick2016年04月20日 08:48:04 +00:00Commented Apr 20, 2016 at 8:48
-
\$\begingroup\$ I don't know, I'm a C# guy, haven't done Java in ages. Just quickly googled it because I found the absence of a call to Flush odd. \$\endgroup\$BCdotWEB– BCdotWEB2016年04月20日 09:01:37 +00:00Commented Apr 20, 2016 at 9:01
-
\$\begingroup\$ @BCdotWEB Ok ;). Thanks anyway. It was a good hint. \$\endgroup\$Patrick– Patrick2016年04月20日 09:08:41 +00:00Commented Apr 20, 2016 at 9:08
-
1\$\begingroup\$ Refer : flushing buffer writer \$\endgroup\$Ani Menon– Ani Menon2016年04月20日 09:16:42 +00:00Commented Apr 20, 2016 at 9:16
2 Answers 2
If you want to avoid the creation of the *Writers
on each call of writeToCsvFile()
method, one of solutions would be as follows.
Change OutputWriterService
class to implement AutoCloseable
interface. This will allow to put its instances into a try-with-resources
block. The Writers
created inside the original method will become constants in the changed class and they will be closed inside the close()
method when the routine exits from the block (normally or with an exception):
public class OutputWriterService implements AutoCloseable {
private static final String FILE_NAME = "FILE";
private final FileWriter fw;
private final BufferedWriter bw;
private final PrintWriter out;
public OutputWriterService() throws IOException {
this.fw = new FileWriter(FILE_NAME, true);
this.bw = new BufferedWriter(fw);
this.out = new PrintWriter(bw);
}
@Override
public void close() throws IOException {
this.fw.close();
this.bw.close();
this.out.close();
}
public void writeToCsvFile(List<CustomTypeDescription> descriptions){
// ...
}
}
writeToCsvFile()
method becomes shorter:
public void writeToCsvFile(List<CustomTypeDescription> descriptions){
try {
for(CustomTypeDescription description : descriptions){
out.println(description.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
}
By the way, the code of the original createOutputFile()
method looks very suspicious. A cleaner way would be to use
Files.createFile(Paths.get(FILE_NAME));
The instance of the BufferedWriter
can also be created differently:
Files.newBufferedWriter(Paths.get(FILE_NAME),
StandardCharsets.UTF_8,
StandardOpenOption.APPEND);
This makes the FileWriter
instance unnecessary.
Now, the user of your OutputWriterService
class should proceed as follows:
try (OutputWriterService service = new OutputWriterService()) {
// May be called as many times as desired, depending on the algorithm
// The same instances of the writers will be reused.
service.writeToCsvFile(descriptions);
} // + process the exception or rethrow it
There is no need to flush, because any buffered data not already written will be flushed at the end of the try
block. This is because a close()
operation automatically flushes remaining data, and you guarantee that everything will be closed at the end of the try
block by declaring your closable resources between the parentheses at the top of the try
block.