2010-07-28 9 views
2

나는 정말로 잘 압축되는 (4 : 1) 대용량 파일 (6 ~ 15GB)의 작은 숫자 (2-10)를 가지고 있습니다.Java를 사용하여 실패한 압축 다시 시작

클라이언트와 서버를 Java로 작성 중이므로 클라이언트에서 서버로 파일을 보내므로 이됩니다. 1. 클라이언트가 파일을 보낼 때 압축합니다 (즉, 중간 .zip 파일 없음
2. 서버의 압축 된 내용은 올바른 형식의 파일 (예 : .zip 또는 .tgz 파일)로 끝나기 때문에 '있는 그대로'다운로드 할 수 있습니다. 이 모두

가 처음 두가 java.io 소켓과 자바를 사용하여 아주 쉽게 달성 할 수있는 새로운 과정에서 발생할 수있는 전송을 재개
4. 중순 방법을 실패 할 경우
3. 전송이 재개 될 수 있습니다. util.zip ZipOutputStreams. 세 번째는 나를 슬픔의 원인으로 만든다. 네 번째는 실제로 컨텍스트입니다.

나는 해결책이 아마도 일종의 부분적인 재전송이나 사전을 만들기 위해 다시 구문 분석을 요구할 것이라고 생각한다.

재개 가능한 압축을 지원하는 Java 라이브러리가 있습니까?

+0

두 사람이 청킹을 제안했습니다. 이것은 위의 조건 (2)을 제외하고는 좋은 생각입니다. 만약 내가 덩어리면, 나는 (내가 알고있는) 청크에서 유효한 .zip/.gz 파일을 만드는 방법이 없다. –

+0

내가 말했듯이 클라이언트에 파일을 저장하거나 서버에 다시 어셈블해야합니다. 유일한 대안은 효과적으로 전체 파일을 메모리에로드하고 어쨌든 클라이언트에서 파일의 메모리 내 버전을 만드는 것입니다. – cletus

답변

2

필요한 방식으로 재개 가능한 압축을 지원하는 미리 제작 된 라이브러리를 찾을 수 없습니다. 그러나 오픈 라이센스에 따라 직접 작성할 수있는 많은 것들이 있습니다. 이제는 질문에 설명 된 모든 제약 조건을 충족시키는 클라이언트/서버 솔루션을 얻었습니다.

아이디어는 위에서 설명한 청크 아이디어와 비슷하지만 서버가 청크를 관리하고 클라이언트의 압축 된 청크를 서버의 압축 된 청크에 매핑하는 부기를 수행합니다. 솔루션에 임시 파일이 없습니다.

 
(1) The client sends a manifest to the server, containing the 
    to-be contents of the zip file 
(2) The server sends back an ID for the manifest 
    Then repeatedly 
    (3) The client asks the server "is there anything still 
     required for the manifest with ID X" 
    (4) The server replies "no", or with a manifest entry 
     for a file in the manifest, plus a offset and length to send 
    (5) The client compresses that chunk and sends it (plus some 
     bookkeeping info) 
    (6) The server puts the chunk into the every growing zip file, 
     plus appropriate zip file crud. If the server orders 
     the chunks it asks the client for appropriately, this can 
     all be done by file appends. 

서버는 (서버 또는 클라이언트에 충돌 포함) 3-6 단계 중 고장 안전 (잘, 더 재개 될 수 있도록마다 6 단계가 성공적으로 완료 매니페스트 업데이트를 다음과 같이 기본 프로토콜입니다 이하).

청크 와이즈 zip 파일 생성을 수행하는 데 조금 비판적이었던 몇 가지 비트가 있습니다. 달성해야 할 기본 사항은 청크 가능 압축 알고리즘을 찾는 것입니다. 수축은 이러한 방식으로 사용될 수 있습니다.

자바 ZipOutputStream 및 DeflaterOutputStream은 임의의 플러시를 허용하지 않으므로 '청크 와이즈'디플레이션/압축에 적합하지 않습니다. http://www.jcraft.com/jzlib에는 ZLib의 BSD 스타일 라이선스 된 Java 구현이 있습니다. 필자는 속도를 벤치마킹하지 않았지만 Java 구현과 동일한 결과를 제공합니다. JZLib는 훌륭하고 ZLib의 모든 플러시 모드를 지원합니다 (java.util.zip.Deflate 구현과 달리).

또한 Zip 파일은 각 항목에 대해 CRC를 계산합니다. 따라서 4 단계의 매니페스트 항목에는 '부분적인'CRC가 포함되어 있습니다. 각 부분은 업데이트되고 5 단계의 장부 정보로 다시 전송됩니다. http://www.axlradius.com/freestuff/CRC32.java에 java에 대한 공개 CRC 구현이 있습니다. 나는 그것을 벤치마킹했으며 네이티브 java 구현만큼 빠르며 동등한 CRC를 제공합니다.

마지막으로, Zip 파일 형식은 꽤 당황 스럽습니다. 필자는 위키 피 디아 페이지와 http://www.pkware.com/documents/casestudies/APPNOTE.TXT에서 대부분의 구현을 함께 처리했습니다. 어느 시점에서 필자는 필드 중 하나에 대해 올바른 값을 사용할 수 없었습니다. 다행히도 JDK의 ZipOutputStream 소스를 사용하면 자신이하는 일을 볼 수 있습니다.

0

스트림 중간에서 압축을 다시 시작할 수있는 기능에 대해서는 알지 못합니다. 그것은 매우 국가에 민감한 것 같아요.

대신 파일을 작은 덩어리로 나누어 개별적으로 보낼 수 있습니다 (압축 사용). 100 킬로 청크 (예 :)라고 말하십시오. 여전히 청크의 중간에서 다시 시작할 수는 없지만 가장 최근의 청크 시작 부분에서 쉽게 시작할 수 있습니다.

0

비행 중에 압축하는 것은 쉽습니다. 문제는 업로드를 다시 시작하는 것입니다. 기본적으로 HTTP를 전송 수단으로 사용하지 않으므로 (S) FTP 또는 SCP와 같은 것을 볼 필요가 있습니다. 심지어 문제는 클라이언트에서 파일을 생성하지 않으므로 다시 시작될 것입니다. 최소한 결정론적인 압축 방법을 사용해야합니다 (지정된 파일이 주어지면 두 번의 압축 알고리즘 실행 모두 정확히 동일한 출력을 생성 함을 의미). 이것이 사실이 아니라면 을 다시 시작할 수 없습니다..

제 조언은 약간 접선 식으로 접근하는 것입니다. 파일을 관리 가능한 덩어리로 나누십시오 (예 : 50MB). 그것은 결정 론적입니다. 각 청크를 개별적으로 압축합니다. 청크가 실패하면 다시 보내십시오. 다시 시작하지는 않지만 클라이언트가 수신했거나 기다리고있는 청크를 클라이언트에게 알려주는 서버의 부분 업로드를 얻을 수 있습니다.

하나의 문제는 특정 파일을 식별하는 것입니다. 파일 이름이 맞습니까? 다른 식별 특성이 있습니까? 두 명의 클라이언트가 동일한 파일을 업로드하려고하면 서버가이를 감지 할 수 있습니까? 이런 종류의 표준 접근법은 체크섬 (파일 내용의 SHA1 해시)을 사용하는 것이지만 체크섬을 수행하기 위해 전체적으로 16GB 파일을 읽지 않으려 고합니다. 그래서 다른 방법이 바람직합니다.

네트워크 통신이 이런 식 상상해

Client: SEND file1234 CHUNKS 167 
Server: RECEIVED (already got) or WAIT 7 (chunk #) 
Client: compress and send chunk 7 
Server: WAIT 8 
.... 

이 방법은 또한 다른 클라이언트는 다른 덩어리를 요청과 함께 병합 할 수있는 서버와 동일한 시간에 파일을 업로드 여러 클라이언트를 처리합니다.

이 방법의 한 가지 문제는 파일이 서버에서 "완료되지 않았습니다"(zip 또는 tarball처럼) 파일이지만 실제로 끝낼 수있는 무언가로 끝내야한다고 생각합니다. 코드 작성에 악몽이 되십시오.

+0

파일을 이름으로 식별 할 수 있다고 가정하는 것이 안전합니다 (실제로는 그보다 조금 복잡하지만 ID 협상은 시스템의 다른 곳에서 처리됩니다). (또한 청킹 아이디어에 대한 답으로 질문 자체에 대한 주석을 참조하십시오.) –

관련 문제