2013-03-25 1 views
11

큰 파일 (예 : 2GB)에서 마지막 n 줄을 읽어야합니다. 파일은 UTF-8로 인코딩됩니다.Java의 RandomAccessFile이 메모리의 전체 파일을 읽습니까?

가장 효율적인 방법을 알고 싶습니다. Java의 RandomAccessFile에 대해 읽으십시오. 그러나 seek() 메소드는 메모리에있는 전체 파일을 읽습니다. 네이티브 구현을 사용하므로 소스 코드를 참조 할 수 없었습니다.

+0

아니요. 'seek()'은 전체 파일을 제외하고 메모리에 * anything *을 읽지 않습니다. 너는 모든 권한을 가지고있다. – NPE

+0

그 질문을 통해 읽었지만 UTF-8로 인코딩 된 파일의 경우 RandomAccessFile을 사용하면 낙담한지 이해하고 싶습니다. –

+1

복제본에 동의하지 않습니다. 이것은 RandomAccessFile에 더 초점을 맞추고, 다른 하나는 응용 프로그램에 대한 것이고 RAF는 언급하지 않습니다. –

답변

6

1) RandomAccessFile.seek는 파일 포인터의 현재 위치 만 설정하고 바이트는 메모리에 읽지 않습니다.

2) 파일이 UTF-8로 인코딩되었으므로이 파일은 텍스트 파일입니다. 우리가 일반적으로 BufferedReader를 사용하는 텍스트 파일을 읽기 위해 Java 7은 File.newBufferedReader를 추가하여 파일에서 텍스트를 읽는 BufferedReader의 인스턴스를 만들었습니다. 마지막 n 라인을 읽는 것은 비효율적 일 수도 있지만 구현하기 쉽습니다.

3) 효율적이기 위해서는 RandomAccessFile이 필요하고 끝에서부터 파일을 거꾸로 읽어야합니다. 여기 LF 그것은 바이트를 반전하는 라인을 작성 도달하면, 기본적인 예

public static void main(String[] args) throws Exception { 
    int n = 3; 
    List<String> lines = new ArrayList<>(); 
    try (RandomAccessFile f = new RandomAccessFile("test", "r")) { 
     ByteArrayOutputStream bout = new ByteArrayOutputStream(); 
     for (long length = f.length(), p = length - 1; p > 0 && lines.size() < n; p--) { 
      f.seek(p); 
      int b = f.read(); 
      if (b == 10) { 
       if (p < length - 1) { 
        lines.add(0, getLine(bout)); 
        bout.reset(); 
       } 
      } else if (b != 13) { 
       bout.write(b); 
      } 
     } 
    } 
    System.out.println(lines); 
} 

static String getLine(ByteArrayOutputStream bout) { 
    byte[] a = bout.toByteArray(); 
    // reverse bytes 
    for (int i = 0, j = a.length - 1; j > i; i++, j--) { 
     byte tmp = a[j]; 
     a[j] = a[i]; 
     a[i] = tmp; 
    } 
    return new String(a); 
} 

그것은 꼬리에있는 ByteArrayOutputStream 바이트 시작한 후 파일 바이트를 판독한다.

두 가지 개선 할 필요가 : 1) 버퍼링 2) EOL 인식

+1

전체 파일을 읽지 않고 BufferedReader를 사용하는 방법을 포함 할 수 있습니까? –

+0

한 줄씩 읽으므로 전체 파일을 메모리로 읽지 않습니다. –

+0

처음부터 줄 단위로 읽는 것이므로 전체 파일을 메모리로 읽어 들이고 있습니다. 전체 파일을로드하지 않더라도 한 번에 파일. –

0

당신이 랜덤 액세스를해야하는 경우 RandomAccessFile에 필요합니다. 자신이하는 일을 알고 있다면 바이트를 UTF-8로 변환 할 수 있습니다.

BuffredReader를 사용하는 경우 skip (n)을 문자 수만큼 사용할 수 있습니다. 즉, 전체 파일을 읽어야합니다.


이렇게 조합하는 방법; FileInputStream을 skip()과 함께 사용하고 N 개 줄 바꾸기를 읽고 BufferedReader에서 스트림을 래핑하여 UTF-8 인코딩으로 줄을 읽으려는 곳을 찾으십시오.

+0

결국, 하루가 끝나면 전체 파일을 읽는 것입니다. 기억에? –

+0

내가 제안한대로하지 않는다. BufferedReader를 단독으로 사용하면 전체 파일을 읽을 수 있습니다. 그렇게하는 것이 좋습니다. –

+0

이 초보자를위한 코드 스 니펫을 공유 할 수 있습니까? (. 파일 끝까지 도달하고, n 줄까지 추적 한 다음, n 줄을 내 메모리에서 읽으려고합니다. –

관련 문제