2009-07-15 9 views
1

파일의 하위 집합을 다른 파일로 복사해야하는 Java로 시스템을 구축하고 있습니다 (반드시 파일의 시작 부분이 아님). 나는. simultaneosuly 그래서 스레드 - 수 과정이 필요한 파일에서 다른 파일로 효율적으로 복사

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

여러 스레드가 동일한 소스 파일에서 읽고 (다른 오프셋 (offset)하지만) 동일한 대상 파일에 기록 될 수있다 : 나는 다음과 같은 매개 변수가 안전합니다 (즉, 쓰레드가 쓰거나 읽는 동안 다른 쓰레드가 파일에서 찾는 것을 방지합니다).

어떻게 구현하나요? RandomAccessFile 또는 Java NIO를 사용해야합니까? 어떤 종류의 자물쇠를 구입해야합니까? 예 : RandomAccessFile 인스턴스가 파일에 대한 시스템 전체 잠금을 자동으로 가져 오나요, 아니면 별도로 유지해야합니까?

편집 : randomAccessFile.getChannel().tryLock()은 시스템 전반의 잠금을 가져 오지만 호출 스레드가 아닌 VM이 보유하고있는 것으로 보입니다. 그래서 내가 사용하고 있다면 스레드에 대한 잠금을 획득해야합니다 (또는 소스와 대상 파일을 잠글 필요가 있기 때문에 실제로 두 개를 확보해야합니다).

답변

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에 byte-by-byte를 쓰지 않도록 중간 버퍼에 읽은 데이터를 저장해야합니다. – Yrlec

관련 문제