2013-10-23 5 views
3
Path file = Paths.get("c:/large.log"); 
    AsynchronousFileChannel channel = AsynchronousFileChannel.open(file); 
    final ByteBuffer buffer = ByteBuffer.allocate(1000); 
    channel.read(buffer, 0, buffer, 
     new CompletionHandler<Integer, ByteBuffer>() { 
     public void completed(Integer result, ByteBuffer attachment) { 
      System.out.println(new String(buffer.array())); 
     } 
    }); 

이렇게하면 large.log에서 처음 1000 바이트를 읽을 수 있습니다. ByteBuffer.allocate (1000 * 1000) 같은 더 큰 바이트 배열을 할당하고 싶지 않다면 어떻게 로그를 읽을 수 있습니까? 왜냐하면 이것이 OutOfMemory로 이어질 것이라고 생각하기 때문입니다.AsynchronousFileChannel은 큰 파일을 어떻게 읽을 수 있습니까?

누군가 샘플 코드를 제공 할 수 있습니까? 감사합니다.

ps : java.io.BufferedReader.read()의 반환 값을 확인할 수 있으므로 JIO로 큰 파일을 루프로 읽을 수 있습니다. 그러나 NIO2를 사용하는 방법을 알지 못합니다.

답변

-1

파일에 남아있는 것이 있으면 completionHandler에서 다른 읽기를 시작하십시오. 하지만 적어도 1000보다 더 큰 버퍼를 사용합니다.

+0

나는 다른 읽기를 시작하지만 여전히 처음 1000 바이트를 읽습니다. –

+0

저에게 맞습니다. 물론 버퍼를 지우고 읽음에서 position 매개 변수를 증가시켜야하므로 최종 변수로 약간의 혼란이 있지만 그렇게 할 수 있습니다. – EJP

+0

@downvoter 설명해주십시오. – EJP

3

다음은 작동하는 해킹입니다.

당신이주의 할 것 몇 가지가 :

  1. 난 그냥 출력에 대한 귀하의 buffer.array() 사용했습니다. buffer.clear()를 사용하여 위치를 다시 설정해야 비동기 읽기에서 1000 스페어 바이트가 표시되지만 배열의 기존 데이터는 지워지지 않습니다. 결과적으로 파일의 끝에 도달하면 1000 바이트 미만을 읽으면 전체 버퍼가 인쇄됩니다. 그러나 방금 읽은 바이트 수와 나머지 1000 바이트는 버퍼 끝에 있습니다. 실생활에서 그 일에 대해 뭔가를하고 싶을 것입니다. (아마도 결과 나 버퍼의 위치와 함께)
  2. completed 메서드 내에서 클래스 변수 인 buffer을 사용할 수 없다는 이유 때문에 channel 그것은 또한 클래스 변수입니다 null입니다. 나는 아직 그 이유가 무엇인지 알지 못했습니다. 그래서 그것을 변경했습니다 버퍼 대신 첨부 파일로 channel. 여전히 나를 이해가되지 않습니다.
  3. 비동기 읽기 스레드 jvm을 계속 실행하는 데 중요하지 않습니다. 따라서 메인 메서드의 끝에 read을 붙이면됩니다. Enter을 눌러 종료하십시오.
  4. 클래스 변수 pos mai 읽는 파일의 위치를 ​​지정합니다.
  5. 마법은 complete 방법 중에 다른 비동기 읽기를 시작할 때 발생합니다. 그래서 익명의 클래스를 버리고 인터페이스 자체를 구현했습니다.
  6. 경로를 다시 자신의 것으로 전환하고 싶을 것입니다.

재미있게 보내십시오.

import java.nio.*; 
import java.nio.channels.*; 
import java.nio.file.*; 
import java.io.IOException; 

public class TryNio implements CompletionHandler<Integer, AsynchronousFileChannel> { 

     // need to keep track of the next position. 
     int pos = 0; 
     AsynchronousFileChannel channel = null; 
     ByteBuffer buffer = null; 

     public void completed(Integer result, AsynchronousFileChannel attachment) { 
       // if result is -1 means nothing was read. 
       if (result != -1) { 
         pos += result; // don't read the same text again. 
             // your output command. 
         System.out.println(new String(buffer.array())); 

         buffer.clear(); // reset the buffer so you can read more. 
       } 
         // initiate another asynchronous read, with this. 
       attachment.read(buffer, pos , attachment, this); 


     } 
     public void failed(Throwable exc, 
         AsynchronousFileChannel attachment) { 
       System.err.println ("Error!"); 
       exc.printStackTrace(); 
     } 

     public void doit() { 
       Path file = Paths.get("/var/log/syslog"); 
       AsynchronousFileChannel channel = null; 
       try { 
         channel = AsynchronousFileChannel.open(file); 
       } catch (IOException e) { 
         System.err.println ("Could not open file: " + file.toString()); 
         System.exit(1); // yeah. heh. 
       } 
       buffer = ByteBuffer.allocate(1000); 

       // start off the asynch read. 
       channel.read(buffer, pos , channel, this); 
       // this method now exits, thread returns to main and waits for user input. 
     } 

     public static void main (String [] args) { 
       TryNio tn = new TryNio(); 
       tn.doit(); 
      // wait fur user to press a key otherwise java exits because the 
      // asynch thread isn't important enough to keep it running. 
       try { System.in.read(); } catch (IOException e) { } 
     } 
} 
+0

이 샘플 코드를 실행했습니다. 그러나 실제 로그 파일보다 더 많은 내용을 인쇄합니다. –

+2

System.out.print (new String (buffer.array(), 0, result)); 다른 정크 데이터가 인쇄됩니다. –

+0

정확히,이 문제는 OP의 원래 코드에 있음을 유의하십시오. – EJP

관련 문제