Эффективное копирование из одного файла в другой - PullRequest
1 голос
/ 16 июля 2009

Я строю систему на Java, которая должна копировать часть файла в другой файл (не обязательно в начало файла). То есть У меня есть следующие параметры:

File srcFile, File dstFile, long srcFileOffset, long dstFileOffset, long length

Несколько потоков могут одновременно считывать из одного и того же исходного файла и записывать в один и тот же файл назначения (хотя и с разными смещениями), поэтому мне нужно, чтобы процесс был безопасным для потоков (то есть предотвращал поиск других потоков в файле ветка пишет / читает).

Как бы вы это реализовали? Должен ли я использовать RandomAccessFile или Java NIO? Какие замки мне нужно приобрести? Например. экземпляр RandomAccessFile автоматически получает общесистемную блокировку файла или мне нужно хранить ее отдельно?

Edit: похоже, что randomAccessFile.getChannel().tryLock() получает блокировку всей системы, но она удерживается виртуальной машиной, а не вызывающим потоком. Поэтому, если я использую это, то мне нужно также получить блокировку для потока (или даже две, поскольку мне нужно заблокировать как исходный, так и целевой файл).

Ответы [ 2 ]

2 голосов
/ 16 июля 2009

Я написал небольшой тестовый код. Кажется, работает без проблем на 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();
    }
}
1 голос
/ 16 июля 2009

Вы можете просто открыть FileInputStream в srcFile, пропустить (srcFileOffset) и читать оттуда. Но для записи в целевой файл с определенным смещением вам понадобится RandomAccessFile.

Что касается блокировки, вы можете использовать одиночный файл для чтения / записи из файла и синхронизации методов чтения / записи на вашем объекте.

...