2009-07-15 11 views
1

ファイルのサブセットを別のファイルにコピーする必要があるJavaのシステムを構築しました(必ずしもファイルの先頭ではない)。私。 simultaneosulyので、私はスレッドするプロセスが必要あるファイルから別のファイルへの効率的なコピー

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

複数のスレッドが同じソース・ファイルからの読み取りと、(異なるオフセットを持つが)同じ宛先ファイルに書き込むことができます:私は、次のパラメータを持っています安全です(つまり、スレッドが書き込み/読み取り中に他のスレッドがファイルを探してしまうのを防ぐ)。

これはどのように実装しますか? RandomAccessFileまたはJava NIOを使用する必要がありますか?どのようなロックを取得する必要がありますか?例えば。 RandomAccessFileインスタンスは自動的にファイルのシステム全体のロックを取得するのですか、それとも別に保持する必要がありますか?

編集:randomAccessFile.getChannel().tryLock()はシステム全体のロックを取得しますが、VMによって保持されており、呼び出し元のスレッドではありません。だから私はそれを使用している場合、私はスレッドのロックを取得する必要が(または2つの実際に私は両方のソースと宛先ファイルをロックする必要があるため)。

答えて

2

小さなテストコードを作成しました。 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(); 
    } 
} 
+0

興味深いことに、私はseekによって設定された位置がRandomAccessFileインスタンスのためにローカルであると思います。同じファイルへの書き込みアクセスでいくつかのインスタンスを開き、ディスクリプタ内の別々の位置を保持できることはわかりませんでした。 – Yrlec

1

あなただけの、SRCFILE上のFileInputStreamを開きます(srcFileOffset)をスキップし、そこから読み取ることができます。しかし、あるオフセットで宛先ファイルに書き込むには、RandomAccessFileが必要です。

ロックについては、シングルトンを使用してファイルから読み書きでき、オブジェクトの読み込み/書き込みメソッドを同期できます。

+0

+1。おそらく、ランダムアクセスの合理化によってIOパフォーマンスも向上するはずです。 – akarnokd

+0

ありがとう、私はそれを試してみます。それから私はちょうどいくつかの中間バッファに読み込まれたデータを格納する必要があるので、それをRandomAccessFileにバイト単位で書き込まないでください。 – Yrlec

関連する問題