Reputation: 3458
I'm building a system in Java which has to copy a subset of a file into another file (not necessarily to the beginning of the file). I.e. I have the following parameters:
File srcFile, File dstFile, long srcFileOffset, long dstFileOffset, long length
Several threads could be reading from the same source-file and writing to the same destination-file (although with different offsets) simultaneosuly so I need the process to be thread-safe (i.e. preventing other threads from seeking in the file while a thread is writing/reading).
How would you implement this? Should I use a RandomAccessFile or Java NIO? What kind of locks do I need to acquire? E.g. does a RandomAccessFile-instance automatically acquire a system-wide lock on the file or do I need to keep that separately?
Edit: Looks like randomAccessFile.getChannel().tryLock()
acquires a system-wide lock but it's held by VM, not the calling thread. So if I'm using that then I need to acquire a lock for the thread as well (or two actually since I need to lock both the source- and destination-file).
Upvotes: 1
Views: 2169
Reputation: 5159
you can just open a FileInputStream on srcFile, skip(srcFileOffset), and read from there. But to write on the destination file at a certain offset, you will need RandomAccessFile.
As for locking, you can use a singleton to read/write from the file and synchronize the read/write methods on your object.
Upvotes: 1
Reputation: 69997
I've composed a small test code. Seems to work without problems on WinXP:
import java.io.RandomAccessFile;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MultiRAF {
public static void main(String[] args) throws Exception {
RandomAccessFile raf = new RandomAccessFile("testraf.dat", "rw");
raf.setLength(4096);
raf.close();
ExecutorService exec = Executors.newCachedThreadPool();
for (int k = 0; k < 4; k++) {
final int offset = k * 1024;
final int kid = k;
exec.submit(new Runnable() {
public void run() {
try {
RandomAccessFile raf = new RandomAccessFile(
"testraf.dat", "rw");
for (int j = 0; j < 100; j++) {
System.out.printf("%d accessing%n", kid);
byte[] data = new byte[1024];
for (int i = 0; i < data.length; i++) {
data[i] = (byte)i;
}
raf.seek(offset);
raf.write(data);
System.out.printf("%d done%n", kid);
}
raf.close();
} catch (Exception ex) {
System.err.printf("%d failed%n", kid);
ex.printStackTrace();
}
};
});
}
exec.shutdown();
}
}
Upvotes: 2