2010-09-01 73 views
14

Tôi có thể tìm thấy nhiều chức năng cho phép bạn giải nén tệp GZip, nhưng làm cách nào để giải nén chuỗi GZip?Giải nén chuỗi GZip trong Java

Tôi đang cố gắng phân tích cú pháp phản hồi HTTP trong đó nội dung phản hồi được nén bằng GZip. Tuy nhiên, toàn bộ phản ứng được lưu trữ đơn giản trong một chuỗi sao cho một phần của chuỗi chứa ký tự nhị phân.

Tôi đang cố gắng sử dụng:

byte responseBodyBytes[] = responseBody.getBytes(); 
ByteArrayInputStream bais = new ByteArrayInputStream(responseBodyBytes); 
GZIPInputStream gzis = new GZIPInputStream(bais); 

Nhưng đó chỉ ném một ngoại lệ: java.io.IOException: Không ở định dạng GZIP

Trả lời

14

Không có những điều như một chuỗi Gzip. GZip là nhị phân, chuỗi là văn bản.

Nếu bạn muốn nén chuỗi, trước tiên bạn cần chuyển đổi nó thành nhị phân - ví dụ: với OutputStreamWriter bị xích vào một nén OutputStream (ví dụ một GZIPOutputStream)

Tương tự như vậy để đọc dữ liệu, bạn có thể sử dụng một InputStreamReader bị xích vào một nén InputStream (ví dụ một GZIPInputStream).

Một cách dễ dàng đọc từ Reader là sử dụng CharStreams.toString(Readable) từ Guava hoặc thư viện tương tự.

+0

Tôi đang cố gắng phân tích cú pháp phản hồi HTTP trong đó nội dung phản hồi được nén bằng GZip. Tuy nhiên, toàn bộ phản ứng được lưu trữ đơn giản trong một chuỗi sao cho một phần của chuỗi chứa ký tự nhị phân. Bạn có nói rằng không thể chuyển đổi chuỗi GZip này thành chuỗi văn bản không? – Matt

+0

@Matt: Bạn không nên lưu trữ phản hồi trong chuỗi để bắt đầu. Nếu nó là nhị phân, nó không nên có trong văn bản ở tất cả, trừ khi nó là base64. Khái niệm "một phần của chuỗi chứa dữ liệu nhị phân" thực sự không hoạt động. Có vẻ như bạn cần thay đổi cách tiếp cận của mình. –

+0

Phản hồi ban đầu được trình bày dưới dạng một byte [], vì vậy đó là tất cả những gì tôi có. Tôi có thể sử dụng cái này không? – Matt

1

Lý tưởng nhất là bạn nên sử dụng thư viện cấp cao để xử lý nội dung này cho bạn. Bằng cách đó bất cứ khi nào một phiên bản mới của HTTP được phát hành, người bảo trì thư viện hy vọng sẽ làm tất cả công việc khó khăn cho bạn và bạn chỉ cần phiên bản cập nhật của thư viện.

Điều đó sang một bên, đó là một bài tập tốt để thử tự mình làm.

Giả sử bạn đang đọc Phản hồi HTTP dưới dạng luồng byte từ ổ cắm TCP. Nếu không có mã hóa gzip, thì việc đưa toàn bộ phản hồi vào chuỗi có thể hoạt động. Tuy nhiên, sự hiện diện của tiêu đề "Nội dung Mã hóa: gzip" có nghĩa là nội dung phản hồi (như bạn đã lưu ý) là nhị phân.

Bạn có thể xác định phần bắt đầu của nội dung phản hồi làm byte đầu tiên sau lần xuất hiện đầu tiên của chuỗi "\ r \ n \ r \ n" (hoặc 4 byte 0x0d, 0x0a, 0x0d, 0x0a).

Mã hóa gzip có tiêu đề đặc biệt, và bạn nên kiểm tra 3 byte cơ thể đầu tiên cho rằng:

   byte[] buf; // from the HTTP Response stream 
       // ... insert code here to populate buf from HTTP Response stream 
       // ... 
       int bodyLen = 1234; // populate this value from 'Content-length' header 
       int bodyStart = 123; // index of byte buffer where body starts 
       if (bodyLen > 4 && buf[bodyStart] == 0x1f && buf[bodyStart + 1] == (byte) 0x8b && buf[bodyStart + 2] == 0x08) { 
        // gzip compressed body 
        ByteArrayInputStream bais = new ByteArrayInputStream(buf); 
        if (bodyStart > 0) bais.skip(bodyStart); 

        // Decompress the bytes 
        byte[] decompressedBytes = new byte[bodyLen * 4]; 
        int decompressedDataLength = 0; 
        try { 
         // note: replace this try-catch with try-with-resources here where possible 
         GZIPInputStream gzis = new GZIPInputStream(bais); 
         decompressedDataLength = gzis.read(decompressedBytes); 
         gzis.close(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
       } 

Các "Không có trong định dạng GZIP" lỗi được sản xuất bởi GZIPInputStream nếu 3 byte đầu tiên không khớp với các giá trị tiêu đề GZIP ma thuật, vì vậy việc kiểm tra các giá trị này sẽ giúp giải quyết vấn đề cụ thể của bạn.

Ngoài ra còn có một kiểm tra CRC trong định dạng GZIP, tuy nhiên nếu thiếu hoặc không chính xác, bạn sẽ thấy một lỗi khác.

Các vấn đề liên quan