2013-11-25 87 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