2

This is the clearest means I've seen of appending lines to a file. (and creating the file if it doesn't already exist)

String message = "bla";
Files.write(
    Paths.get(".queue"),
    message.getBytes(),
    StandardOpenOption.CREATE,
    StandardOpenOption.APPEND);

However, I need to add (OS) locking around it. I've browsed through examples of FileLock, but can't find any canonical examples in the Oracle Java tutorials, and the APIs are pretty impenetrable to me.

fred
  • 1,812
  • 3
  • 37
  • 57

3 Answers3

2

Not around this code. You would have to open the file via a FileChannel, acquire the lock, do the write, close the file. Or release the lock and keep the file open, if you prefer, so you only have to lock next time. Note that file locks only protect you against other file locks, not against code like you posted.

user207421
  • 305,947
  • 44
  • 307
  • 483
2

You can lock a file retrieving it stream channel and locking it.

Something amongs the line of :

new FileOutputStream(".queue").getChannel().lock();

You can also use tryLock depending on how smooth you want to be.

Now to write and lock, your code would looks like this :

try(final FileOutputStream fos = new FileOutputStream(".queue", true);
    final FileChannel chan = fos.getChannel()){
    chan.lock();
    chan.write(ByteBuffer.wrap(message.getBytes()));
}

Notice that in this example, I used Files.newOutputStream to add your opening options.

Jean-François Savard
  • 20,626
  • 7
  • 49
  • 76
  • @fred Got access to computer, edited. That is right, if the only option needed is append, then we can pass directly a boolean as one of the constructors expect the append flag. – Jean-François Savard Jul 29 '16 at 03:41
1

You can apply a lock to a FileChannel.

 try {
        // Get a file channel for the file
        File file = new File("filename");
        FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

        // Use the file channel to create a lock on the file.
        // This method blocks until it can retrieve the lock.
        FileLock lock = channel.lock();

        /*
           use channel.lock OR channel.tryLock();
        */

        // Try acquiring the lock without blocking. This method returns
        // null or throws an exception if the file is already locked.
        try {
            lock = channel.tryLock();
        } catch (OverlappingFileLockException e) {
            // File is already locked in this thread or virtual machine
        }

        // Release the lock - if it is not null!
        if( lock != null ) {
            lock.release();
        }

        // Close the file
        channel.close();
    } catch (Exception e) {
    }

For more you can go through this tutorials:

  1. How can I lock a file using java (if possible)
  2. Java FileLock for Reading and Writing
Community
  • 1
  • 1
SkyWalker
  • 28,384
  • 14
  • 74
  • 132