Плохое кодирование JAR-файла с сокетами - PullRequest
0 голосов
/ 30 марта 2012

В настоящее время я пытаюсь запустить сервер сокетов, который должен получать сообщения с французскими символами, такими как "àéèîï" и т. Д.

Итак, вот в чем дело: когда я запускаю свой сервер сокетов в затмении, сообщенияу меня правильная кодировка, потому что я вижу акценты в консоли.Но когда я экспортирую свой сервер сокетов в исполняемый 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поскольку он очень длинный, но в основном он просто управляет соединениями и реализует BufferedReader с InputStreamReader, чтобы иметь возможность читать полученные сообщения следующим образом:

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();
    }

Вот и все для кода.Теперь в командной строке отображаются мои результаты, когда я указываю кодировку UTF-8 в моем классе 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: ??

А теперь, когда я не указываю кодировку в моем классе 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 часов, я пробовал все найденные в Интернете решения, но ни одно из них не помогло: (

Пожалуйста, мне нужна помощь!

Спасибо, Рафаэль

1 Ответ

3 голосов
/ 02 апреля 2012

Помните, что ваша консоль Windows не использует ни UTF-8, ни ISO-8859-1. Вероятно, он использует CP850.

Вы увидите, например, что éèï кодируется как байты E9 E8 EF с ISO-8859-1, который декодируется как ÚÞ´ с CP850.

Я советую записать все как UTF-8, прочитать все как UTF-8 и проверить вывод, записав в текстовый файл и открыв его с помощью редактора UTF-8, вместо того, чтобы доверять тому, что вы видите в консоли.

Также убедитесь, что компилятор Java использует ту же кодировку (-encoding), что и редактор, с помощью которого вы редактируете исходный код Java, в котором он сохраняется. Я настоятельно рекомендую UTF-8.

Кроме того, это URLDecoder.decode(...) не делает то, что вы думаете, что делает. То есть в лучшем случае он ничего не делает, так как это не противоположность String.getBytes(...). Удалите его, если вы фактически не отправляете данные в кодировке URL.

InputStreamReader уже декодирует байты до String с. Для симметрии вы должны использовать OutputStreamWriter на другом конце.

Обязательно всегда, всегда , всегда используйте версии методов, которые позволяют указывать кодировку.

  • Никогда не используйте String.getBytes() без указания кодировки.
  • Никогда не используйте new String(byte[]) без указания кодировки.
  • Никогда не используйте new InputStreamReader(InputStream) без указания кодировки.
  • Никогда не используйте new OutputStreamWriter(OutputStream) без указания кодировки.
  • и т. Д.

Желательно всегда использовать версии, которые принимают CharsetEncoder или CharsetDecoder, так как они могут быть настроены на исключение при неудачном кодировании / декодировании.

Всякий раз, когда вы не указываете кодировку везде, где это возможно, вы зависите от кодировки по умолчанию платформы, которая по сути является глобальной переменной со случайным значением .

Каждое место, где вы случайно использовали кодировку платформы по умолчанию, является ошибкой, которая может ждать, пока не проявится, пока вы или кто-то еще не попробуете программу на другой платформе или в другой стране.

...