2

Suppose a Java application writes to a file using BufferedWriter API (and does not call flush after every write). I guess that if the application exits with System.exit the buffer is not flushed and so the file might be corrupted.

Suppose also that the application component, which decides to exit, is not aware of the component, which writes to the file.

What is the easiest and correct way to solve the "flush problem" ?

Michael
  • 41,026
  • 70
  • 193
  • 341
  • 1
    Obviously, "easiest" and "correct" are mutually exclusive. ;-) Would it be "easy" to change the writer into a `PrintWriter`? You could then utilize `autoFlush` on newlines. – tmh Sep 09 '13 at 15:57

2 Answers2

5

You may use the Runtime.addShutdownHook method, which can be used to add a jvm shutdown hook. This is basically a unstarted Thread, which executes on shutdown of the Java Virtual Machine.

So if you have a handle of the file available for that thread, then you can try to close the stream and flush the output.

Note: Although it seems feasible to use this, but I believe there will be implementation challenges to it because of the fact that whether your file handle is not stale when your shutdown hook is called. So the better approach should be to close your streams gracefully using finally blocks in the code where file operations are done.

Juned Ahsan
  • 67,789
  • 12
  • 98
  • 136
  • I believe you can call `close()`, since the docs say "Closing a previously closed stream has no effect." – Dan Oct 22 '15 at 12:31
1

You can add a shutdown hook but you need to have a reference to each of these BufferedWriter or other Flushable or Closable objects. You won't gain anything from it. You should perform close() and flush() directly in the code that is manipulating the object.

Think of the Information Expert GRASP pattern, the code manipulating the BufferedWriter is the place that has the information about when an operation is finished and should be flushed, so that's where that logic should go.

If some application component is calling System.exit when things aren't done, I would consider that an abnormal exit, should not return 0 and therefore shouldn't guarantee that streams are flushed.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • So that means if I have a Logger for my program that contains read and write methods to different logs, I am going to have to create and then close a newBufferedWriter for each time I want to write to a log file, since "You should perform close() and flush() directly in the code that is manipulating the object."? – JohnMerlino Jul 10 '14 at 15:38
  • @John No, you can open a single `BuferredWriter` for the duration of the application and use that to write to your file. Part of the _write_ operation should probably `flush()` from time to time. – Sotirios Delimanolis Jul 10 '14 at 15:46