2016-12-13 7 views
0

Java NIO 프레임 워크를 사용하여 대용량 파일에서 효과적으로 읽고 대량 데이터를 파일에 쓸 수 있습니다.Java NIO를 사용하여 큰 파일 읽기 및 쓰기

나는 ByteBufferFileChannel 함께 일하고 있어요 아래 같은 것을 시도했다 :

public static void main(String[] args) 
{ 
    String inFileStr = "screen.png"; 
    String outFileStr = "screen-out.png"; 
    long startTime, elapsedTime; 
    int bufferSizeKB = 4; 
    int bufferSize = bufferSizeKB * 1024; 

    // Check file length 
    File fileIn = new File(inFileStr); 
    System.out.println("File size is " + fileIn.length() + " bytes"); 
    System.out.println("Buffer size is " + bufferSizeKB + " KB"); 
    System.out.println("Using FileChannel with an indirect ByteBuffer of " + bufferSizeKB + " KB"); 

    try ( FileChannel in = new FileInputStream(inFileStr).getChannel(); 
      FileChannel out = new FileOutputStream(outFileStr).getChannel()) 
    { 
     // Allocate an indirect ByteBuffer 
     ByteBuffer bytebuf = ByteBuffer.allocate(bufferSize); 

     startTime = System.nanoTime(); 

     int bytesCount = 0; 
     // Read data from file into ByteBuffer 
     while ((bytesCount = in.read(bytebuf)) > 0) { 
      // flip the buffer which set the limit to current position, and position to 0. 
      bytebuf.flip(); 
      out.write(bytebuf); // Write data from ByteBuffer to file 
      bytebuf.clear(); // For the next read 
     } 

     elapsedTime = System.nanoTime() - startTime; 
     System.out.println("Elapsed Time is " + (elapsedTime/1000000.0) + " msec"); 
    } 
    catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
} 

사람이 있다면이 같은 절차를 따라야합니다, 말할 수 2 GB 이상의 내 파일 크기?

서면 작업이 대량 인 경우 작문하는 동안 비슷한 일을하고 싶다면 어떻게해야합니까?

+0

자바 7. 이후 FileInputStream/FileOutputStream 우회하지 않고 open a FileChannel directly 당신은 사이에서 데이터를 처리하려고하거나 그냥 복사 할 수 있습니까? – Kayaman

+1

'비슷한 일을하고 싶다면'은 무엇을 의미합니까? – EJP

답변

1

Files.copy(Paths.get(inFileStr),Paths.get(outFileStr), StandardCopyOption.REPLACE_EXISTING)을 사용하여 예제 코드 에서처럼 파일을 복사 할 수 있습니다. 단 한 줄의 코드 만 사용하면 더 빠를 것입니다. 이미 두 개의 파일 채널을 개설 한 경우

그렇지 않으면, 당신은 단지 out 채널로 in 채널의 전체 내용을 전송하는
in.transferTo(0, in.size(), out)를 사용할 수 있습니다. 이 메소드는 소스 파일 내에서 대상 채널의 현재 위치 (처음에는 0 임)로 전송되는 범위를 지정하고 반대 방법으로 소스 채널의 현재 데이터에서 데이터를 전송하는 방법도 있습니다 (예 : out.transferFrom(in, 0, in.size())). 위치는 대상 파일 내의 절대 범위로 지정하십시오.

그들은 함께 Java 사이드 버퍼에 데이터를 복사 할 필요없이 거의 모든 상상할 수있는 중요하지 않은 대량 전송을 효율적인 방법으로 허용합니다. 그것이 당신의 요구를 해결하지 못한다면, 당신은 당신의 질문에보다 구체적이어야합니다. 그런데

, 당신은

0
while ((bytesCount = in.read(bytebuf)) > 0) { 
     // flip the buffer which set the limit to current position, and position to 0. 
     bytebuf.flip(); 
     out.write(bytebuf); // Write data from ByteBuffer to file 
     bytebuf.clear(); // For the next read 
    } 

복사 루프가 올바르지 않습니다. 그것은해야한다 : 내 파일 크기 [가] 2 GB 이상의 경우

while ((bytesCount = in.read(bytebuf)) > 0 || bytebuf.position() > 0) { 
     // flip the buffer which set the limit to current position, and position to 0. 
     bytebuf.flip(); 
     out.write(bytebuf); // Write data from ByteBuffer to file 
     bytebuf.compact(); // For the next read 
    } 

아무도 말할 수

, 나는 같은 절차를 수행해야합니까?

예. 파일 크기는 아무런 차이가 없습니다.

+0

파일 크기가 큰 경우이 변경은 어떻게 영향을 미칩니 까? – KayV

+0

불완전한 쓰기가 손실되지 않도록하고 마지막으로 읽은 부분을 플러시합니다. 이 코드는 0부터 모든 파일 크기에서 작동합니다. – EJP