2016-08-01 4 views
-4

ByteArrayOutputStream을 사용하여 크기가 1KB에서 10GB 사이의 파일을 쓰려고하는데 다음과 같은 예외가 발생합니다. 나는 jdk 6을 사용하고 있습니다. 더 나은 성능의 Api를 제안하십시오. 동일한 네트워크 상자를 사용하여 읽고 쓰고 있습니다.Byteoutputstream을 사용하여 Java를 작성하는 거대한 파일

Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit 
     at java.util.Arrays.copyOf(Unknown Source) 
     at java.io.ByteArrayOutputStream.grow(Unknown Source) 
     at java.io.ByteArrayOutputStream.ensureCapacity(Unknown Source) 
     at java.io.ByteArrayOutputStream.write(Unknown Source) 
     at java.io.OutputStream.write(Unknown Source) 
     at 

코드 :

import java.io.BufferedOutputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 


public class PrepareFile { 

    /** 
    * @param args 
    * @throws Exception 
    */ 
    public static void main(String[] args) throws Exception { 
     // TODO Auto-generated method stub 

     new PrepareFile().constructFile("f:\\hello","f:\\output",10000000); 

    } 

    //Writes a large file of 10 GB using input file data of small size by duplicating 
    public void constructFile(String fileName, String outPath, int multiplier) throws Exception { 
     BufferedOutputStream fos = null; 
     FileInputStream fis = null; 

     final File inputFile = new File(fileName); 
     String path = inputFile.getParent(); 
     if (outPath != null && !outPath.isEmpty()) { 
      path = outPath; 
     } 

     fis = new FileInputStream(fileName); 

     try { 



      // read the transactions in the input file. 
      byte[] txnData = new byte[(int) inputFile.length()]; 
      fis.read(txnData); 

      final File outFile = new File(path, "Myfile"); 
      fos = new BufferedOutputStream(new FileOutputStream(outFile)); 
      final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      final ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); 

      //multiplier if input file size is 1 KB and output file is 10 GB, then multiplier value is (1024*1024) 

      for (long i = 1; i <= multiplier; i++) { 

       if(i >=40000 && i % 40000==0){ 
        System.out.println("i value now: "+i); 
        baos.writeTo(fos); 
        baos.reset(); 
        //baos.write(txnData); 
       } 

       // write transactions 
       baos.write(txnData); 
       baos1.write(txnData); //Exception is coming at this line 
      } 

      int Padding = myCustomMethod(baos1.toByteArray()); 

      // write all out data to the output stream 
      baos.writeTo(fos); 

      baos.flush(); 
      baos1.flush(); 
     } catch(Exception e){ 
      e.printStackTrace(); 
     }finally { 
      fos.close(); 
      fis.close(); 
     } 

    } 

    public int myCustomMethod(byte[] b){ 

     //Need complete bytes to prepare the file trailer 
     return 0; 
    } 


} 
+2

* 왜 * 10Gb를 'ByteArrayOutputStream'에 쓰고 있습니까? 당신이 뭔가를하고있는 이유를 말하지 않으면 아무도 "더 나은"것을 제안 할 수 없습니다. ByteArrayOutputStream을 전혀 사용하지 않아야하는 것처럼 보입니다. 메모리가 아닌 의도 한 대상에 직접 쓰지 않는 것이 좋습니다. –

+1

메모리가 부족합니다. 파일에 * 쓰는 것과 같은 다른 기술을 사용하십시오. – chrylis

+0

코드를 표시하십시오 –

답변

2

크기가 부호있는 32 비트이기 때문에 당신은 ByteArrayOutputStream 2 GB 이상의 버퍼를 가질 수 없습니다.

성능을 원한다면 파일을 점진적으로 처리하고 비용이 많이 드는 대용량 메모리 복사본은 피할 것입니다.

저는 라이브러리가 2GB보다 큰 버퍼를 지원하며, 힙 사용을 피하기 위해 기본 메모리를 사용하고 파일에 매핑 할 수 있으며 주 메모리보다 클 수 있습니다.

그러나 데이터를 점진적으로 처리하면 큰 버퍼가 필요하지 않습니다.

나는 또한 (10 년 전에 출시 된) 자바 6 코드를 기반으로


EDIT보다 더 나은 64 비트 작업을 수행 당신이 자바 8을 사용하는 것이 좋습니다,있는 ByteArrayOutputStream를 사용할 필요가 없습니다 점진적으로 파일을 준비 할 수 있습니다.

//Writes a large file of 10 GB using input file data of small size by duplicating 
public void constructFile(String fileName, String outFileName, int multiplier) throws IOException { 
    byte[] bytes; 
    try (FileInputStream fis = new FileInputStream(fileName)) { 
     bytes = new byte[fis.available()]; 
     fis.read(bytes); 
    } 

    try (FileOutputStream fos = new FileOutputStream(outFileName)) { 
     for (int i = 0; i < multiplier; i++) { 
      fos.write(bytes); 
     } 
    } 

    // now process the file "outFileName" 
    // how depends on what you are trying to do. 
    // NOTE: It is entirely possible the file should be processed as it is written. 
} 
+0

복사 한 코드 스 니펫을 살펴보고 크로니클 바이트를 사용하여 어떻게 10 GB 파일? – Susanta

+0

간단한 예제를 추가 하겠지만, 당신이해야 할 일에 달려 있습니다. 어떤 처리가 필요하다고 말할 수 있습니까? –

+0

@Susanta는 질문의 코드를 기반으로 예제를 추가했습니다. –

관련 문제