2013-11-25 93 views
2

我試圖從默認字符編碼爲UTF-8的服務器向默認字符編碼爲的客戶端發送一個字符串windows-1252通過套接字PrintWriterPrintWriter over Socket OutputStream導致數據損壞/丟失

當我運行下面的客戶端時,儘管我嘗試使用CharsetDecoder來轉換字符串,但我並沒有收到141的原始值。

作爲一個控制測試,我已經嘗試在Eclipse中運行這兩個類,並強制通過下面的對話使用UTF-8作爲默認編碼系統 - 並且我觀察到當兩個客戶端都使用UTF -8,輸出在客戶端被成功解釋。

更新:它看起來像我能夠流字節和恢復初始格式,但爲了這樣做,我必須知道在服務器上使用的編碼。在這種情況下沒有某種圖書館會有用嗎?我寧願不會被迫以字節數組的形式傳輸數據。

Eclipse Dialog

服務器:

import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 

//Runs on a server with default character encoding of UTF-8 
public class TestServer { 

public static void main(String[] args) throws Exception { 

    PrintWriter writer = null; 
    ServerSocket serverSocket = null; 
    try { 

     int x = 141; 
     String s = "#" + (char)x; 

     serverSocket = new ServerSocket(5555); 
     Socket clientSocket = serverSocket.accept(); 

     writer = new PrintWriter(
         (new OutputStreamWriter(clientSocket.getOutputStream())), true); 

     System.out.println((int)s.charAt(1)); 
     writer.write(s); 
    } catch(Exception e) { 

     e.printStackTrace(); 
    } finally { 

     writer.close(); 
     serverSocket.close(); 
    } 
} 
} 

客戶:

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.net.Socket; 
import java.nio.ByteBuffer; 
import java.nio.CharBuffer; 
import java.nio.charset.Charset; 
import java.nio.charset.CharsetDecoder; 

//Runs on a server with default character encoding of windows-1252 
public class TestClient { 

public static void main(String[] args) throws Exception { 

    Socket s = new Socket("localhost", 5555); 
    BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream())); 

    String string = reader.readLine(); 
    System.out.println((int)string.charAt(1)); //prints 194 when it was 141 on the other end 

    //Charset.defaultCharset returns windows-1252 
    CharsetDecoder decoder = Charset.defaultCharset().newDecoder(); 
    CharBuffer buffer = decoder.decode(ByteBuffer.wrap(string.getBytes())); 
    String convertedString = buffer.toString(); 

    System.out.println((int)convertedString.charAt(1)); //still prints 194 

    String convertedString2 = new String(string.getBytes(), "UTF-8"); 
    System.out.println((int)convertedString2.charAt(1)); //prints 65533 ?? 

    s.close(); 
} 
} 

回答

2

我發現有OutputStreamWriter和InputStreamReader構造函數將字符集作爲參數。這是我去的解決方案:

發件人:

out = new PrintWriter(
    new BufferedWriter(new OutputStreamWriter(
     socket.getOutputStream(), "UTF-8")), true); 

在接收器:

in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); 
0

我只想write()一個byte[]直接向OutputStream,避免中間人,然後構造一個新的客戶端的字符串fr om返回byte[]。 PrintWriter的文件說:

它不包含用於寫入原始字節,用於該程序 應該使用未編碼的字節流的方法。

在新的服務器代碼你必須:

bytep[] s = new String("#" + (char)x).getBytes();; 
    Socket clientSocket = serverSocket.accept(); 
    OutputStream writer = clientSocket.getOutputStream(); 
    System.out.println((int)s.charAt(1)); 
    writer.write(s); 

在客戶端,你需要創建一個ByteArrayInputStream和字節轉換爲字符串:

byte[] return_data = null; 
Socket s = new Socket("localhost", 5555); 
BufferedInputStream bis = new BufferedInputStream(s.getInputStream()); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
int byte_read = bis.read(); 
while(byte_read != -1) 
{ 
    baos.write(byte_read); 
    byte_read = bis.read(); 

} 

return_data = baos.toByteArray(); 
bis.close(); 
baos.close(); 

String s = new String(return_data); 
+0

嗯..我看到了作爲一個選項,但我真的想避免。是否還有其他更高級別的OutputStream實現可以使用? – kwikness

+0

我認爲它實際上使用byte []方法的代碼實際上稍少一些。查看我提供的代碼示例。 – mttdbrd

+0

謝謝。我猜這會起作用,但是你的解決方案不提供在客戶端不知道服務器字符編碼的情況下解碼的方法。另外,我真的很喜歡不需要讀/寫字節的解決方案。 – kwikness