2012-06-11 44 views
5

byte Tôi có một vấn đề trong mã:GZIP chuỗi giải nén và chuyển đổi

private static String compress(String str) 
{ 
    String str1 = null; 
    ByteArrayOutputStream bos = null; 
    try 
    { 
     bos = new ByteArrayOutputStream(); 
     BufferedOutputStream dest = null; 

     byte b[] = str.getBytes(); 
     GZIPOutputStream gz = new GZIPOutputStream(bos,b.length); 
     gz.write(b,0,b.length); 
     bos.close(); 
     gz.close(); 

    } 
    catch(Exception e) { 
     System.out.println(e); 
     e.printStackTrace(); 
    } 
    byte b1[] = bos.toByteArray(); 
    return new String(b1); 
} 

private static String deCompress(String str) 
{ 
    String s1 = null; 

    try 
    { 
     byte b[] = str.getBytes(); 
     InputStream bais = new ByteArrayInputStream(b); 
     GZIPInputStream gs = new GZIPInputStream(bais); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     int numBytesRead = 0; 
     byte [] tempBytes = new byte[6000]; 
     try 
     { 
      while ((numBytesRead = gs.read(tempBytes, 0, tempBytes.length)) != -1) 
      { 
       baos.write(tempBytes, 0, numBytesRead); 
      } 

      s1 = new String(baos.toByteArray()); 
      s1= baos.toString(); 
     } 
     catch(ZipException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
    catch(Exception e) { 
     e.printStackTrace(); 
    } 
    return s1; 
} 

public String test() throws Exception 
    { 
     String str = "teststring"; 
     String cmpr = compress(str); 
     String dcmpr = deCompress(cmpr); 
} 

này java.io.IOException đang ném: định dạng lạ (kỳ diệu số ef1f)

GZIPInputStream gs = new GZIPInputStream(bais); 

Nó chỉ ra rằng khi chuyển đổi byte new String (b1)byte b [] = str.getBytes() byte là "hư hỏng". Tại đầu ra của dòng, chúng ta đã có nhiều byte hơn. Nếu bạn tránh chuyển đổi thành chuỗi và làm việc trên dòng có byte - mọi thứ đều hoạt động. Xin lỗi vì tiếng Anh của tôi.


public String unZip(String zipped) throws DataFormatException, IOException { 
    byte[] bytes = zipped.getBytes("WINDOWS-1251"); 
    Inflater decompressed = new Inflater(); 
    decompressed.setInput(bytes); 

    byte[] result = new byte[100]; 
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 

    while (decompressed.inflate(result) != 0) 
     buffer.write(result); 

    decompressed.end(); 

    return new String(buffer.toByteArray(), charset); 
} 

Tôi sử dụng chức năng này để giải nén máy chủ phản ứng. Cảm ơn vì sự giúp đỡ.

Trả lời

7

Bạn có hai vấn đề:

  • Bạn đang sử dụng mã hóa ký tự mặc định để chuyển đổi chuỗi gốc vào byte. Điều đó sẽ thay đổi theo nền tảng. Tốt hơn là chỉ định mã hóa - UTF-8 thường là một ý tưởng hay.
  • Bạn đang cố gắng trình bày dữ liệu nhị phân mờ đục của kết quả nén dưới dạng chuỗi bằng cách chỉ cần gọi hàm tạo String(byte[]). Nhà xây dựng đó chỉ có chỉ có nghĩa là dữ liệu được mã hóa văn bản ... mà điều này không phải là. Bạn nên sử dụng base64 cho việc này. Có một số public domain base64 library giúp việc này trở nên dễ dàng. (Ngoài ra, không chuyển đổi dữ liệu nén thành văn bản chút nào - chỉ cần trả lại một mảng byte.)

Về cơ bản, bạn cần phải hiểu cách dữ liệu và dữ liệu nhị phân khác nhau - khi bạn muốn chuyển đổi giữa hai , bạn nên cẩn thận. Nếu bạn muốn đại diện cho dữ liệu nhị phân "không phải văn bản" (tức là byte mà không phải là kết quả trực tiếp của văn bản mã hóa) trong chuỗi, bạn nên sử dụng thứ gì đó như base64 hoặc hex. Khi bạn muốn mã hóa một chuỗi dưới dạng dữ liệu nhị phân (ví dụ: để viết một số văn bản vào đĩa), bạn nên cẩn thận xem xét mã hóa nào sẽ sử dụng. Nếu một chương trình khác sẽ đọc dữ liệu của bạn, bạn cần phải tìm hiểu xem mã hóa nào mong đợi - nếu bạn có toàn quyền kiểm soát nó, tôi thường đi UTF-8.

Bên cạnh đó, việc xử lý ngoại lệ trong mã của bạn là người nghèo:

  • Bạn nên hầu như không bao giờ bắt Exception; bắt ngoại lệ cụ thể hơn
  • Bạn không nên chỉ bắt ngoại lệ và tiếp tục như thể nó chưa bao giờ xảy ra. Nếu bạn không thể thực sự xử lý ngoại lệ và vẫn hoàn thành phương pháp thành công, bạn nên để cho bong bóng ngoại lệ lên ngăn xếp (hoặc có thể nắm bắt nó và bọc nó theo loại ngoại lệ phù hợp hơn cho sự trừu tượng của bạn)
+0

Tôi sử dụng default_charset() == "UTF-8". Đây chỉ là thử nghiệm. –

+0

@AlexandrErofeev: Sẽ không rõ khi ai đọc * Mã * Mã hóa bạn đang sử dụng. IMO nó tốt hơn nhiều để nói rõ ràng. (Và nếu nó chỉ là một thử nghiệm, loại bỏ tất cả các xử lý ngoại lệ hoàn toàn, và chỉ để cho tất cả các phương thức ném 'IOException' - nó sẽ đơn giản hóa mã.) –

2

Khi bạn GZIP nén dữ liệu, bạn luôn nhận được dữ liệu nhị phân. Dữ liệu này không thể được chuyển đổi thành chuỗi vì nó không phải là dữ liệu ký tự hợp lệ (trong bất kỳ mã hóa nào).

Vì vậy, phương pháp nén bạn nên trả về một mảng byte và phương pháp giải nén bạn nên tham gia một mảng byte như tham số của nó.

Hơn nữa, tôi khuyên bạn nên sử dụng mã hóa rõ ràng khi bạn chuyển đổi chuỗi thành một mảng byte trước khi nén và khi bạn chuyển dữ liệu giải nén thành chuỗi một lần nữa.

+0

Thực tế rằng đây chỉ là một thử nghiệm. Trong thực tế, từ máy chủ, tôi nhận được một chuỗi json mà sẽ là chìa khóa "zip". Chứa dữ liệu nén. Tôi có thể lấy nội dung của một khóa như một chuỗi. Sau đó, tôi cần phải trích xuất thông tin này. –

+0

@AlexandrErofeev: Tất cả những điều này là thông tin bạn nên đưa vào câu hỏi. Tôi nghi ngờ JSON bao gồm dữ liệu được mã hóa base64 ... đó là cách tôi hy vọng * nó sẽ đại diện cho dữ liệu nhị phân. –

+0

JSON không thể trực tiếp chứa dữ liệu nhị phân. Vì vậy, nếu khóa được mã hóa GZIP, có thể mã hóa Base64 sẽ chuyển dữ liệu nhị phân thành một chuỗi mà JSON có thể chứa. Bạn có lẽ nên thêm một mẫu JSON có khóa cho câu hỏi của bạn. – Codo

0

Khi bạn GZIP nén dữ liệu, bạn luôn nhận được dữ liệu nhị phân. Không thể chuyển đổi dữ liệu này thành chuỗi vì nó không phải là dữ liệu ký tự hợp lệ (trong bất kỳ mã hóa nào).

Codo là đúng, cảm ơn rất nhiều vì đã khai sáng cho tôi. Tôi đã cố gắng giải nén một chuỗi (được chuyển đổi từ dữ liệu nhị phân). Những gì tôi đã sửa đổi đã sử dụng InflaterInputStream trực tiếp trên luồng đầu vào được trả về bởi kết nối http của tôi. (Ứng dụng của tôi đang truy xuất một chuỗi JSON lớn)

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