带套接字的Runnable JAR文件坏编码

时间:2012-03-30 16:26:28

标签: sockets encoding jar runnable

我目前正在尝试运行需要接收带有法语字符的消息的套接字服务器,例如“àéèîï”等。

所以,这是交易:当我在eclipse中执行我的套接字服务器时,我收到的消息具有正确的编码,因为我可以在控制台中看到重音符号。但是当我将套接字服务器导出到一个可运行的jar文件并在命令提示符下执行时,我收到的消息的编码似乎是错误的。

我知道有很多关于这个问题的帖子,但没有一个解决方案对我有用,或者我可能遗漏了一些东西。

这是一些代码: 对于我的套接字服务器:

server = new SocketServer(port, SocketServer.ASCIIINPUT) {

    @Override
    public void processMessage(String message, Socket sender) throws MessageException {
        try{
            System.out.println("Message without decoding : " + message);
            System.out.println("Message with UTF-8 decoding : " + URLDecoder.decode(message, "UTF-8"));
            System.out.println("Message with ISO-8859-1 decoding : " + URLDecoder.decode(message, "ISO-8859-1"));
        } catch(Exception ex){
            ex.printStackTrace();
        }
    }

    @Override
    public void socketIterationDone() {}

};

我不会发布我的SocketServer的代码,因为它很长但它基本上只是管理连接并使用InputStreamReader实现BufferedReader,以便能够读取收到的消息,如下所示:

final BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.forName("UTF-8")));

我也尝试过没有指定Charset:

final BufferedReader reader = new BufferedReader(new InputStreamReader(in));

这是我的套接字客户端:

try {
        Socket s = new Socket("127.0.0.1", 6005);
        s.getOutputStream().write("With UTF-8 encoding: éèï\n".getBytes(Charset.forName("UTF-8")));
        s.getOutputStream().write("With ISO-8859-1 encoding: éèï\n".getBytes(Charset.forName("ISO-8859-1")));
        s.getOutputStream().write("Without encoding: éèï".getBytes());
        s.close();
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

这就是代码。现在,当我在SocketServer类中指定Charset UTF-8时,在命令提示符中有我的结果:

C:\Users\nx_vostro_1\Desktop>java -jar test.jar
Server listening on port: 6005
Message without decoding : With UTF-8 encoding: ÚÞ´
Message with UTF-8 decoding : With UTF-8 encoding: ÚÞ´
Message with ISO-8859-1 decoding : With UTF-8 encoding: ÚÞ´
Message without decoding : With ISO-8859-1 encoding: ???
Message with UTF-8 decoding : With ISO-8859-1 encoding: ???
Message with ISO-8859-1 decoding : With ISO-8859-1 encoding: ???
Message without decoding : Without encoding: ??
Message with UTF-8 decoding : Without encoding: ??
Message with ISO-8859-1 decoding : Without encoding: ??

C:\Users\nx_vostro_1\Desktop>java -Dfile.encoding=UTF-8 -jar test.jar
Server listening on port: 6005
Message without decoding : With UTF-8 encoding: ├®├¿├»
Message with UTF-8 decoding : With UTF-8 encoding: ├®├¿├»
Message with ISO-8859-1 decoding : With UTF-8 encoding: ├®├¿├»
Message without decoding : With ISO-8859-1 encoding: ´┐¢´┐¢´┐¢
Message with UTF-8 decoding : With ISO-8859-1 encoding: ´┐¢´┐¢´┐¢
Message with ISO-8859-1 decoding : With ISO-8859-1 encoding: ´┐¢´┐¢´┐¢
Message without decoding : Without encoding: ´┐¢´┐¢
Message with UTF-8 decoding : Without encoding: ´┐¢´┐¢
Message with ISO-8859-1 decoding : Without encoding: ´┐¢´┐¢

C:\Users\nx_vostro_1\Desktop>java -Dfile.encoding=ISO-8859-1 -jar test.jar
Server listening on port: 6005
Message without decoding : With UTF-8 encoding: ÚÞ´
Message with UTF-8 decoding : With UTF-8 encoding: ÚÞ´
Message with ISO-8859-1 decoding : With UTF-8 encoding: ÚÞ´
Message without decoding : With ISO-8859-1 encoding: ???
Message with UTF-8 decoding : With ISO-8859-1 encoding: ???
Message with ISO-8859-1 decoding : With ISO-8859-1 encoding: ???
Message without decoding : Without encoding: ??
Message with UTF-8 decoding : Without encoding: ??
Message with ISO-8859-1 decoding : Without encoding: ??

现在我没有在SocketServer类中指定Charset:

C:\Users\nx_vostro_1\Desktop>java -jar test.jar
Server listening on port: 6005
Message without decoding : With UTF-8 encoding: ├®├¿├»
Message with UTF-8 decoding : With UTF-8 encoding: ├®├¿├»
Message with ISO-8859-1 decoding : With UTF-8 encoding: ├®├¿├»
Message without decoding : With ISO-8859-1 encoding: ÚÞ´
Message with UTF-8 decoding : With ISO-8859-1 encoding: ÚÞ´
Message with ISO-8859-1 decoding : With ISO-8859-1 encoding: ÚÞ´
Message without decoding : Without encoding: ÚÞ´
Message with UTF-8 decoding : Without encoding: ÚÞ´
Message with ISO-8859-1 decoding : Without encoding: ÚÞ´

C:\Users\nx_vostro_1\Desktop>java -Dfile.encoding=UTF-8 -jar test.jar
Server listening on port: 6005
Message without decoding : With UTF-8 encoding: ├®├¿├»
Message with UTF-8 decoding : With UTF-8 encoding: ├®├¿├»
Message with ISO-8859-1 decoding : With UTF-8 encoding: ├®├¿├»
Message without decoding : With ISO-8859-1 encoding: ´┐¢´┐¢´┐¢
Message with UTF-8 decoding : With ISO-8859-1 encoding: ´┐¢´┐¢´┐¢
Message with ISO-8859-1 decoding : With ISO-8859-1 encoding: ´┐¢´┐¢´┐¢
Message without decoding : Without encoding: ´┐¢´┐¢
Message with UTF-8 decoding : Without encoding: ´┐¢´┐¢
Message with ISO-8859-1 decoding : Without encoding: ´┐¢´┐¢

C:\Users\nx_vostro_1\Desktop>java -Dfile.encoding=ISO-8859-1 -jar test.jar
Server listening on port: 6005
Message without decoding : With UTF-8 encoding: ├®├¿├»
Message with UTF-8 decoding : With UTF-8 encoding: ├®├¿├»
Message with ISO-8859-1 decoding : With UTF-8 encoding: ├®├¿├»
Message without decoding : With ISO-8859-1 encoding: ÚÞ´
Message with UTF-8 decoding : With ISO-8859-1 encoding: ÚÞ´
Message with ISO-8859-1 decoding : With ISO-8859-1 encoding: ÚÞ´
Message without decoding : Without encoding: ÚÞ´
Message with UTF-8 decoding : Without encoding: ÚÞ´
Message with ISO-8859-1 decoding : Without encoding: ÚÞ´

我很沮丧,我尝试解决这个错误至少30个小时,我尝试了我在互联网上找到的所有解决方案,但没有一个有效:(

拜托,我需要帮助!

谢谢你, 圣拉斐尔

1 个答案:

答案 0 :(得分:3)

请记住,您的Windows控制台既不使用UTF-8也不使用ISO-8859-1。它可能使用CP850

例如,您会看到éèï使用ISO-8859-1编码为字节E9 E8 EF,并使用CP850解码为ÚÞ´

我的建议是将所有内容写为UTF-8,将所有内容都读为UTF-8,并通过写入文本文件并使用具有UTF-8功能的编辑器打开来验证输出,而不是相信什么你在控制台看到了。

还要确保Java编译器使用与您编辑Java源代码的编辑器相同的编码(-encoding)并保存为。我强烈推荐UTF-8

此外,URLDecoder.decode(...)没有按照您的想法行事。也就是说,它最好什么都不做,因为它不是String.getBytes(...)的反面。除非您实际发送URL编码数据,否则将其删除。

InputStreamReader已将字节解码为String s。对于对称性,您应该在另一端使用OutputStreamWriter

确保始终始终始终使用允许您指定编码的方法版本。

  • 如果不指定编码,请勿使用String.getBytes()
  • 如果不指定编码,请勿使用new String(byte[])
  • 如果不指定编码,请勿使用new InputStreamReader(InputStream)
  • 如果不指定编码,请勿使用new OutputStreamWriter(OutputStream)
  • 等等。

最好始终使用带有CharsetEncoderCharsetDecoder的版本,因为这些版本可以配置为在失败的编码/解码时抛出异常。

每当您未在任何可能的地方指定编码时,您都依赖于平台默认编码,该编码基本上是具有随机值的全局变量

您偶然使用平台默认编码的每个地方都是一个错误,可能会等到您或其他人在其他平台或其他国家/地区尝试该程序时才会显示。