0

In C, when I call open() to open a file descriptor, I have to explicitly pass the O_SYNC flag to ensure that writes to this file will be persisted to disk by the time write() returns. If I want to, I can not supply O_SYNC to open(), and then my writes will return much more quickly because they only have to make it into a filesystem cache before returning. If I want to, later on I can force all outstanding writes to this file to be written to disk by calling fsync(), which blocks until that operation has finished. (More details are available on all this in the Linux man page.)

Is there any way to do this in Java? The most similar thing I could find was using a BufferedOutputStream and calling .flush() on it, but if I'm doing writes to randomized file offsets I believe this would mean the internal buffer for the output stream could end up consuming a lot of memory.

Dan
  • 7,155
  • 2
  • 29
  • 54
  • If you're doing writes to random offsets you can't use `BufferedOutputStream` anyway because it's sequential. You'll have to use something like `RandomAccessFile`, but then I don't know how to control its buffering (if there's any at all). You may wish to look at `SeekableByteChannel` created with [Files.newByteChannel](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#newByteChannel-java.nio.file.Path-java.util.Set-java.nio.file.attribute.FileAttribute...-), but I haven't used it so I can't provide a detailed answer. – Sergei Tachenov Mar 12 '16 at 11:26

2 Answers2

1

Using Java 7 NIO FileChannel#force method:

RandomAccessFile aFile = new RandomAccessFile("file.txt", "rw");
FileChannel inChannel = aFile.getChannel();
// .....................
// flushes all unwritten data from the channel to the disk
channel.force(true);

An important detail :

If the file does not reside on a local device then no such guarantee is made.

Bax
  • 4,260
  • 5
  • 43
  • 65
0

Based on Sergey Tachenov's comment, I found that you can use FileChannel for this. Here's some sample code that I think does the trick:

import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;

import static java.nio.file.StandardOpenOption.*;

public class Main {
    public static void main(String[] args) throws Exception {

        // Open the file as a FileChannel.
        Set<OpenOption> options = new HashSet<>();
        options.add(WRITE);
        // options.add(SYNC);     <------- This would force O_SYNC semantics.
        try (FileChannel channel = FileChannel.open(Paths.get("./test.txt"), options)) {

            // Generate a bit data to write.
            ByteBuffer buffer = ByteBuffer.allocate(4096);
            for (int i = 0; i < 10; i++) {
                buffer.put(i, (byte) i);
            }

            // Choose a random offset between 0 and 1023 and write to it.
            long offset = ThreadLocalRandom.current().nextLong(0, 1024);
            channel.write(buffer, offset);
        }
    }
}
Dan
  • 7,155
  • 2
  • 29
  • 54