0

A logic that handles the rollback of a write to a file is this possible?

From my understanding a BufferWriter only writes when a .close() or .flush() is invoked.

I would like to know is it possible to, rollback a write or undo any changes to a file when an error has occurred? This means that the BufferWriter acts as a temporary storage to store the changes done to a file.

  • 1
    BufferedWriter does not ONLY write when close() or flush() is invoke, it will automatically write the values to destination when its buffer is full. You may control the size by initiate it with size argument. To answer your question, bufferedwriter is indeed a storage before done to file as it is a bufferedwriter, you can hold it before writing to destination, but after it is done, you cannot undo it. – PSo Mar 18 '21 at 04:14
  • 1
    This is not supported by the API. Indeed, in general it would be impossible to implement reliably. – Stephen C Mar 18 '21 at 04:15
  • 1
    *"From my understanding a BufferWriter only writes when a .close() or .flush() is invoked."* - This is INCORRECT. Data will also be written when the buffer fills. – Stephen C Mar 18 '21 at 04:16
  • is there a way to implement this rollback to a write then? – user3111115 Mar 18 '21 at 04:20
  • See my first comment. The only way to do it would be to write to (say) a form of buffered writer that stores the entire stream contents in memory until a close or flush. Once data is written to the outbound file descriptor, it cannot be unwritten. – Stephen C Mar 18 '21 at 04:52

2 Answers2

1

How big is what you're writing? If it isn't too big, then you could write to a ByteArrayOutputStream so you're writing in memory and not affecting the final file you want to write to. Only once you've written everything to memory and have done whatever you want to do to verify that everything is OK can you write to the output file. You can pretty much be guaranteed that if the file gets written to at all, it will get written to in its entirety (unless you run out of disk space.). Here's an example:

import java.io.*;    

class Solution {

    public static void main(String[] args) {

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {

            // Do whatever writing you want to do here.  If this fails, you were only writing to memory and so
            // haven't affected the disk in any way.
            os.write("abcdefg\n".getBytes());

            // Possibly check here to make sure everything went OK

            // All is well, so write the output file.  This should never fail unless you're out of disk space
            // or you don't have permission to write to the specified location.
            try (OutputStream os2 = new FileOutputStream("/tmp/blah")) {
                os2.write(os.toByteArray());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

If you have to (or just want to) use Writers instead of OutputStreams, here's the equivalent example:

Writer writer = new StringWriter();
try {

    // again, this represents the writing process that you worry might fail...
    writer.write("abcdefg\n");

    try (Writer os2 = new FileWriter("/tmp/blah2")) {
        os2.write(writer.toString());
    }

} catch (IOException e) {
    e.printStackTrace();
}
CryptoFool
  • 21,719
  • 5
  • 26
  • 44
  • In a spring batch context, i will be able to control the commit interval or even the length of the strings, so the memory here is not a concern for now. I might be in this direction of your suggestion. I come across this class not sure if it can be used TransactionAwareBufferedWriter [link] (https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/support/transaction/TransactionAwareBufferedWriter.html) – user3111115 Mar 18 '21 at 06:15
0

It is impossible to rollback or undo changes already applied to files/streams, but there are tons of alternatives to do so:

One simple trick is to clean the destination and redo the process again, to clean the file:

PrintWriter writer = new PrintWriter(FILE_PATH);
writer.print("");
// other operations
writer.close();

You can remove the content entirely and re-run again.

Or if you are sure the last line(s) are the problems, you may do remove last line actions for your purpose, such as rollback the line instead:

Delete last line in text file

PSo
  • 958
  • 9
  • 25