Ввод Unicode в консольном приложении на Java - PullRequest
5 голосов
/ 29 декабря 2011

Я пытался получить «пользовательский ввод в кодировке Юникод» в моем Java-приложении для небольшого фрагмента служебной программы.Проблема в том, что, похоже, он работает на Ubuntu «из коробки», в которой, как мне кажется, используется кодировка всей ОС в UTF-8, но он не работает в Windows при запуске из «cmd».Рассматриваемый код выглядит следующим образом:

public class SerTest {

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

    public static void testUnicode() throws Exception {
        System.out.println("Default charset: " +
           Charset.defaultCharset().name());
        BufferedReader in  =
           new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
        System.out.printf("Enter 'абвгд эюя': ");
        String line = in.readLine();
        String s = "абвгд эюя";
        byte[] sBytes = s.getBytes();
        System.out.println("strg bytes: " + Arrays.toString(sBytes));
        byte[] lineBytes = line.getBytes();
        System.out.println("line bytes: " + Arrays.toString(lineBytes));
        PrintStream out = new PrintStream(System.out, true, "UTF-8");
        out.print("--->" + s + "<----\n");
        out.print("--->" + line + "<----\n");
    }

}

Вывод в Ubuntu (без каких-либо изменений в конфигурации):

me@host> javac SerTest.java  && java SerTest
Default charset: UTF-8
Enter 'абвгд эюя': абвгд эюя
strg bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
line bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
--->абвгд эюя<----
--->абвгд эюя<----

Вывод в Windows CMDПодсказка (никак не зависит от JAVA_TOOL_OPTIONS):

E:\>chcp 65001
Active code page: 65001

E:\>java -Dfile.encoding=utf8 SerTest
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=utf8
Default charset: UTF-8
Enter 'абвгд эюя': юя': ': абвгд эюя
strg bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
Exception in thread "main" java.lang.NullPointerException
        at SerTest.testUnicode(SerTest.java:26) # byte[] lineBytes = line.getBytes();
        at SerTest.main(SerTest.java:15)

Вывод в консоль Eclipse (после использования JAVA_TOOL_OPTIONS):

Default charset: UTF-8
Enter 'абвгд эюя': абвгд эюя
strg bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=utf8
line bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
--->абвгд эюя<----
--->абвгд эюя<----

В консоли Eclipse, он работает, потому что я добавил общесистемную переменную среды (JAVA_TOOL_OPTIONS), которую, по возможности, я бы хотел избежать.

Вывод в консоль Eclipse (после удаление JAVA_TOOL_OPTIONS):

Default charset: UTF-8
Enter 'абвгд эюя': абвгд эюя
strg bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
line bytes: [-61, -112, -62, -80, -61, -112, -62, -79, -61, -112, -62, -78, -61, -112, -62, -77, -61, -112, -62, -76, 32, -61, -111, -17, -65, -67, -61, -111, -59, -67, -61, -111, -17, -65, -67]
--->абвгд эюя<----
--->абвгд �ю�<----

Итак, мой вопрос: что здесь происходит точно ?Какие изменения кода потребуются, чтобы этот фрагмент работал для всех видов ввода «Unicode»?

Извините за длинный вопрос и заранее спасибо,
Sasuke

Ответы [ 2 ]

4 голосов
/ 30 декабря 2011

Некоторые заметки:

Свойство file.encoding не требуется спецификацией платформы J2SE; это внутренняя деталь реализаций Sun и не должна проверяться или изменяться пользовательским кодом. Он также предназначен только для чтения; технически невозможно поддерживать установку этого свойства в произвольные значения в командной строке или в любое другое время во время выполнения программы.

  • Класс Console обнаружит и использует кодировку терминала, но не поддерживает 65001 (UTF-8) в Windows - по крайней мере, в прошлый раз, когда я пытался это сделать

Я считаю, что правильный документированный способ использования Unicode с cmd.exe - это использование WriteConsoleW и ReadConsoleW.

Я написал пару постов в блоге, когда смотрел на это:

3 голосов
/ 29 декабря 2011

NPE - это броски, когда вы пытаетесь вызвать Arrays.toString(lineBytes), это означает, что lineBytes равно нулю.

lineBytes содержит значение: line.getBytes().getBytes() может возвращать ноль только в том случае, если UnsupportedEncodingException является броском внутри.

Это происходит в Windows, поскольку командная строка Windows не поддерживает Unicode по умолчанию .Это работает в Ubuntu, потому что его командная строка полностью поддерживает Unicode.Он частично работает с eclipse, потому что консольное окно Eclipse - это Java-компонент, который поддерживает Unicode для ввода и делает это для вывода с JAVA_TOOL_OPTIONS.

Суть в том, что вы хотите настроить командную строку windows, чтобы иметь возможность использовать Unicodeперсонажи.Я видел несколько дискуссий на эту тему.Пожалуйста, взгляните на это: Unicode-символы в командной строке Windows - как?

Надеюсь, это поможет вам.

...