2009-11-20 9 views
8

Java 클래스 ZipOutputStream을 통해 하나의 Big 파일 (~ 450 Mbyte)을 압축해야합니다. 이 큰 치수 때문에 JVM 힙 공간의 "OutOfMemory"오류가 발생합니다. 이것은 "zos.write (...)"메서드가 압축하기 전에 내부 바이트 배열로 압축 할 모든 파일 내용을 저장하기 때문에 발생합니다.Java로 ZIP에서 큰 파일을 압축하려면

  origin = new BufferedInputStream(fi, BUFFER); 
     ZipEntry entry = new ZipEntry(filePath); 
     zos.putNextEntry(entry); 

     int count; 
     while ((count = origin.read(data, 0, BUFFER)) != -1) 
     { 
      zos.write(data, 0, count); 
     } 
     origin.close(); 

자연 솔루션은 JVM의 힙 메모리 공간을 확대하는 것입니다,하지만 난 스트리밍 방식으로이 데이터를 쓸 수있는 방법이 있는지 알고 싶습니다. 높은 압축률을 필요로하지 않으므로 알고리즘을 변경할 수도 있습니다.

아무에게도 아이디어가 있습니까?

+1

BUFFER의 크기는 얼마입니까? –

+0

내가 작성한대로 2048 – robob

답변

8

Sam의 답변에 대한 귀하의 의견에 따르면, 분명히 ByteArrayOutputStream을 래핑하는 ZipOutputStream을 만들었습니다. 물론 ByteArrayOutputStream은 압축 된 결과를 메모리에 캐시합니다. 디스크에 기록하려면 ZipOutputStream을 FileOutputStream 주위에 랩핑해야합니다.

+0

좋아요. 당신이 나에게 말한 것을 이해합니다. 그러나 압축 된 데이터는 약 60MByte입니다. "OutOfSpace"힙 오류를 실행하는 데는 부족합니다. 그게 어때? Xmx1024m을 좋게 설정해야합니다! 아마 내 실수예요! – robob

+2

+1, FileOutputStream을 사용하여 zip을 디스크에 쓰거나 브라우저에 직접 스트리밍하려는 경우 HttpServletResponse outputStream을 사용하십시오. –

+1

60 MBytes 메모리를 소모 한 경우 기본 JVM 설정을 사용하고 있습니까? 그렇다면 그 말이 맞다. JVM이 어느 시점에서 64M 힙 크기로 실행되는 경우에도 ByteArrayOutputStream은 바이트 [] 배열을 확장해야합니다. 이는 전체 복사본을 의미합니다. – PSpeed

3

TrueZip라는 라이브러리가 있는데, 저는 이런 종류의 일을하기에 좋은 성공을 거두었습니다.

버퍼링 앞면에서 더 나은지 보장 할 수 없습니다. JDK의 Zip API에 의존하기보다는 자체 코딩으로 많은 작업을 수행한다는 것을 알고 있습니다.

제 생각에는 시도해 볼 가치가 있습니다.

1

ZipOutputStream은 스트림 기반이며 메모리에 보관되지 않습니다. 버퍼가 너무 클 수 있습니다.

+0

내 버퍼는 2048 바이트이며 너무 크다고 생각하지 않습니다! Java 힙 공간 java.util.Arrays.copyOf에서 \t (Arrays.java:2786) java.io.ByteArrayOutputStream의에서 \t : 스레드 "주요"java.lang.OutOfMemoryError와의 예외 : 이는 예외입니다. 물품 (ByteArrayOutputStream.java:94) java.util.zip.DeflaterOutputStream.deflate에서 \t (DeflaterOutputStream.java:161) java.util.zip.DeflaterOutputStream.write에서 \t (DeflaterOutputStream.java:118) 자바에서 \t .util.zip.ZipOutputStream.write (ZipOutputStream.java:272) – robob

0

콘텐츠를 ZipEntry에 저장했기 때문에 ZipEntry를 작성하기 전에 콘텐츠를 기본적으로 모두로드하기 때문에 궁금합니다. Zip을 사용해야합니까? 하나의 데이터 스트림 만 압축해야하는 경우 대신 GZIPOutputStream을 조사 할 수 있습니다. 나는 그것이 같은 문제가 없을 것이라고 생각한다.

희망이 도움이됩니다.

+0

웹 서비스를 통해 보내려면 디렉토리 내용을 Zip 파일에 저장해야합니다. – robob

+2

소리 l 나는 당신이 당신의 응답에 그런 큰 물체를 가지고 있다면 나쁜 생각이다. 대신 zip 파일을 검색 할 수있는 위치에서 URL을 반환하십시오. 일반 서블릿은 바이트 기반 스트리밍 응답을 허용합니다. –

+0

당신이 옳다면 나는 이것이 맞는 선택이라고 생각합니다. – robob

관련 문제