2017-02-06 5 views
0

GZIPOutputStream을 사용하여 클라이언트에서 String을 인코딩하려고 시도하고 GZIPOutputStream을 사용하여 서버에서 문자열을 디코딩하려고합니다.GZIPInputStream 수신자 측에서 디코딩 할 수 없습니다. (유효하지 않은 코드 길이가 설정되었습니다.)

(초기 소켓 연결 설정 이후) 클라이언트 측 코드는 다음과 같습니다 제가 확인

DataInputStream input = new DataInputStream(socket.getInputStream()); 

int length = input.readInt(); 
byte[] buffer = new byte[length]; 
input.readFully(buffer); 

GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(buffer)); 
BufferedReader r = new BufferedReader(new InputStreamReader(gz)); 
String s = ""; 
String line; 
while ((line = r.readLine()) != null) 
{ 
    s += line; 
} 

과 :

// ... Establishing connection, getting a socket object. 
// ... Now proceeding to send data using that socket: 

DataOutputStream out = new DataOutputStream(socket.getOutputStream()); 
String message = "Hello World!"; 

ByteArrayOutputStream out = new ByteArrayOutputStream(); 
GZIPOutputStream gzip = new GZIPOutputStream(out); 
gzip.write(message); 
gzip.close(); 
String encMessage = out.toString(); 

out.writeInt(encMessage.getBytes().length); 
out.write(encMessage.getBytes()); 
out.flush(); 

그리고 서버 측 (연결을 설정 한 후 다시) 코드 버퍼 길이 (즉, 코딩 된 메시지의 크기)가 올바르게 전달되므로 올바른 바이트 수가 전송됩니다. 그러나 나는 이것을 얻고 있습니다 :

java.util.zip.ZipException: invalid code lengths set 
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164) 
at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:117) 
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:122) 
at parsing.ReceiveResponsesTest$TestReceiver.run(ReceiveResponsesTest.java:147) 
at java.lang.Thread.run(Thread.java:745) 

아이디어가 있으십니까?

미리 도움을 청하십시오!

+1

클라이언트 측 gzip.close() 전에 gzip.finish()를 사용해보십시오. GZIP에는 스트림 마지막 부분에 몇 가지 끝 바이트가 필요합니다. – Eugene

+0

Thx Eugene, 결국 문자열로 코딩하는 대신 바이트 스트림을 사용한 다음 해당 문자열을 디코딩하면됩니다. – amirkr

답변

1

귀하는 ByteArrayOutputStreamtoString()을 부르겠습니다. 이것이 틀린 것이며, 여기에서 물어 보는 모든 문자 인코딩 문제가 발생합니다. 대신 toByteArray를 호출해야합니다

byte[] encMessage = out.toByteArray(); 

out.writeInt(encMessage.length); 
out.write(encMessage); 

세부 사항 :

당신이 toString()를 사용하는 경우는, 자바 플랫폼의 기본 문자 인코딩에 바이트 인코딩됩니다. Windows 코드 페이지, UTF-8 등이 될 수 있습니다. 그러나 모든 문자가 올바르게 인코딩 될 수있는 것은 아니며 일부는 대체 문자 (물음표)로 바뀝니다. 세부 사항을 알지 못하면 말할 수 없습니다.

그러나 어떤 경우에는 바이트 배열을 문자열로 인코딩 한 다음이를 쓸 때 다시 바이트 배열로 디코딩하면 바이트 배열의 데이터가 변경 될 가능성이 큽니다. 그리고 그것을 할 필요가 없습니다, 위의 코드 에서처럼 바이트 배열을 바로 가져올 수 있습니다.

+0

우수, 감사합니다! 실제로 바이트 스트림을 쓰는 것이 일을했다! – amirkr

1

왜이 모든 합병증에 빠지십니까? 이 모든 것을 줄일 수 있습니다.

GZIPOutputStream gzip = new GZIPOutputStream(socket.getOutputStream()); 
DataOutputStream out = new DataOutputStream(gzip); 
String message = "Hello World!";  
out.writeUTF(message); 
out.close(); 

// ...  

GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(socket.getInputStream())); 
DataInputStream input = new DataInputStream(gz); 
String line = input.readUTF(); 

코드가 실제로 컴파일되지 않습니다. 메시지가 몇 배 더 커지면 GZipping에 아무런 이점도 없습니다.

+0

안녕하세요, 고마워요. 코드가 "있는 그대로"컴파일되지 않으면 수동으로 다른 컴퓨터의 클라이언트 코드를 복사했습니다. 또한 메시지 문자열이 예제입니다. 실제 메시지는 압축 수를 만드는 15KB를 넘습니다. 답장을 보내 주셔서 감사합니다! – amirkr