2017-05-04 15 views
-6

이 질문은 매우 짧습니다. 나는 파일을예외없이 3GB 파일 읽기

Datei.trec-3,99 GB을 가지고 있고이 코드로 읽어

public class Main { 
    public static void main(String[] args) { 
     byte[] content = null; 
     try { 
      content = Files.readAllBytes(Paths.get("D:", "Videos","Captures","Datei.trec")); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println(content); 
    } 
} 

이 출력입니다 :

Exception in thread "main" java.lang.OutOfMemoryError: Required array size too large 
    at java.nio.file.Files.readAllBytes(Unknown Source) 
    at Main.main(Main.java:13) 

그렇게있다 예외없이 배열을 쓰는 옵션 (FileInputStream ect.)?

+0

콘텐츠가 제한된 크기의 배열이므로 넘쳐납니다. –

+0

대신 콘텐츠를 어떻게 읽어야합니까? – Niton

+3

당신은 그것을 스트리밍합니다. 약간의 데이터 읽기, 당신이 필요로하는 것을하고, 다음 비트 등을 읽으십시오. – pandaadb

답변

3

문제를 모든 데이터를 저장하는 데 필요한 배열에 정의 된, MAX_BUFFER_SIZE보다 큰 것입니다 java.nio.FilesInteger.MAX_VALUE - 8 등 :

public static byte[] readAllBytes(Path path) throws IOException { 
     try (SeekableByteChannel sbc = Files.newByteChannel(path); 
      InputStream in = Channels.newInputStream(sbc)) { 
      long size = sbc.size(); 
      if (size > (long)MAX_BUFFER_SIZE) 
       throw new OutOfMemoryError("Required array size too large"); 

      return read(in, (int)size); 
     } 
    } 

이것은 배열이 정수로 인덱싱되기 때문에 필요합니다. 이것은 얻을 수있는 가장 큰 배열입니다.

당신은 세 가지 옵션이 있습니다 파일입니다

을 통해

스트림, 파일을 열고, '그것은 당신까지 또 다시, 또 다른 덩어리, 공정 읽어 덩어리, 프로세스를 읽고 모든 일을 겪었습니다.

Java는 많은 작업을 수행 할 수있는 클래스를 제공합니다. InputStream, Reader, Scanner 등 - 대부분의 입문 Java 과정 및 서적에서 초기에 논의됩니다. 이 중 하나를 공부하십시오.

예 이것의 유용성은 당신이 무슨 일이 일어날 지 알 수없는 파일의 초기 부분에 가치있는 무언가를 할 수있는에 따라 달라집니다 https://stackoverflow.com/a/21706141/7512

. 이것이 많은 경우입니다. 다른 경우에는 파일을 두 번 이상 통과해야합니다.

파일 형식은 종종 한 번에 처리 할 수 ​​있도록 설계되어 있으므로이를 염두에두고 자신 만의 파일 형식을 디자인하는 것이 좋습니다.

파일이 화면 캡처 된 비디오 인 .trec 파일임을 유의하십시오. 비디오 및 오디오 형식은 특히 스트리밍을 위해 설계 될 가능성이 있습니다. 이는 최종 동영상이 다운로드되기 전에 YouTube 비디오의 시작을 볼 수있는 이유입니다. 메모리 파일을 매핑로

메모리 매핑

당신이 정말로 그것을 처리 할 수있는 파일의 내용 주위에 이동해야하는 경우

, 당신은 그것을 열 수 있습니다.

RandomAccessFile에 대한 설명서를 참조하십시오. 그러면 파일의 데이터에서 임의의 점을 읽을 수 있도록 seek() 메서드가있는 객체가 제공됩니다.

는 난 단지 완전성이 포함 여러 배열

에 읽기; 전체 파일을 힙 메모리에 넣는 것은보기 흉한 일입니다. 그러나 정말로 원한다면 바이트 배열을 여러 배열에 저장할 수 있습니다. 아마도 List<byte[]> 일 것입니다. 자바 틱 의사 코드 :

List<byte[]> filecontents = new ArrayList<byte[]>(); 
    InputStream is = new FileInputStream(...); 
    byte[] buffer = new byte[MAX_BUFFER_SIZE]; 
    int bytesGot = readUpToMaxBufferSizeFrom(file); 
    while(bytesGot != -1) { 
     byte[] chunk = new byte[bytesGot]; 
     System.arrayCopy(buffer, 0, chunk, 0, bytesGot); 
     filecontents.add(chunk); 
    } 

MAX_BUFFER_SIZE * Integer.MAX_INTEGER 바이트로 당신을 수 있습니다. 내용을 액세스하는 것은 단순한 배열을 사용하는 것보다 약간 더 까다 롭다. 그러나 그 구현 세부 사항은 클래스 내부에 숨겨 질 수있다. How to set the maximum memory usage for JVM?

는하지 마 참조 -

당신은 물론, 거대한 힙 크기를 가지고 자바를 구성해야합니다.

+1

사과, 증가하는 힙 크기가 도움이되지 않습니다. 그 부분을 제거하고'MAX_BUFFER_SIZE'에 대해 설명했습니다. – slim

+0

Thanks for Answer – Niton

0

파일을 스트리밍하는 것이 좋습니다. 당신은 아파치 코 몬즈에서, 예를 들어 LineIterator 사용할 수 있습니다

LineIterator it = FileUtils.lineIterator(theFile, "UTF-8"); 
try { 
    while (it.hasNext()) { 
     String line = it.next(); 
    } 
} finally { 
    LineIterator.closeQuietly(it); 
} 
+0

하나의 변수 (배열 또는 데이터 유형)에서 전체 내용을 수집해야합니다 – Niton