【问题标题】:Runnable JAR file bad encoding with sockets带有套接字的可运行 JAR 文件错误编码
【发布时间】:2012-03-30 16:26:28
【问题描述】:

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

所以,这就是交易:当我在 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")));

我也尝试过不指定字符集:

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 类中指定字符集时:

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 个小时,我尝试了我在 Internet 上找到的所有解决方案,但都没有奏效:(

拜托,我需要帮助!

谢谢, 拉斐尔

【问题讨论】:

    标签: sockets encoding jar runnable


    【解决方案1】:

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

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

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

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

    另外,URLDecoder.decode(...) 并没有做你认为它正在做的事情。也就是说,充其量它什么都不做,因为它与String.getBytes(...) 不相反。除非您实际发送的是 URL 编码数据,否则请删除它。

    InputStreamReader 已经将字节解码为Strings。为了对称,你应该在另一端使用OutputStreamWriter

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

    • 切勿在未指定编码的情况下使用String.getBytes()
    • 切勿在未指定编码的情况下使用new String(byte[])
    • 切勿在未指定编码的情况下使用new InputStreamReader(InputStream)
    • 切勿在未指定编码的情况下使用new OutputStreamWriter(OutputStream)
    • 等等。

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

    当您尽可能不指定编码时,您将依赖于平台默认编码,它本质上是具有随机值的全局变量

    您不小心使用平台默认编码的每个地方都是一个错误,它可能会等到您或其他人在另一个平台或另一个国家/地区尝试该程序时才会出现。

    【讨论】:

    • 哦,你说得对,我的数据有正确的编码,只是 DOS 窗口没有正确的输出编码。我尝试将我的数据写入一个文件,它显示了具有正确编码的文本,然后我尝试在运行我的 jar 文件时指定 CP850,它显示了正确的字符。非常感谢克里斯托弗!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2011-10-30
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多