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.
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
@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. –
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