Почему ¿ отображается по-разному в Windows и Linux даже при использовании UTF-8?

StackOverflow https://stackoverflow.com/questions/176196

  •  05-07-2019
  •  | 
  •  

Вопрос

Почему следующее отображается по-разному в Linux и Windows?

System.out.println(new String("¿".getBytes("UTF-8"), "UTF-8"));

в Windows:

¿

в Linux:

¿

Это было полезно?

Решение

System.out.println() выводит текст в системной кодировке по умолчанию, но консоль интерпретирует этот вывод в соответствии со своей собственной настройкой кодировки (или «кодовой страницы»).На вашем компьютере с Windows две кодировки, похоже, совпадают, но на компьютере с Linux выходные данные, очевидно, имеют формат UTF-8, а консоль декодирует их как однобайтовую кодировку, например ISO-8859-1.Или, может быть, как предположил Джон, исходный файл сохраняется как UTF-8 и javac читает его как что-то другое, и этой проблемы можно избежать, используя escape-символы Unicode.

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

new String("¿".getBytes("UTF-8"), "UTF-8")

...не влияет на результат.Все, что для этого нужно, — это кодировать содержимое строки в массив байтов и снова декодировать его, воспроизводя исходную строку — дорогостоящая операция, не требующая никаких операций.Если вы хотите вывести текст в определенной кодировке, вам нужно использовать OutputStreamWriter, например:

FileOutputStream fos = new FileOutputStream("out.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");

Другие советы

Не знаю, в чем именно проблема, но стоит отметить, что

¿ (0xc2,0xbf)

это результат кодировки UTF-8

0xbf,

который является кодовой точкой Unicode для ¿

Итак, в случае с Linux выходные данные отображаются не как utf-8, а как однобайтовая строка.

Проверьте, какую кодировку имеет ваш Linux-терминал.

Для gnome-терминала в Ubuntu — перейдите в меню «Терминал» и выберите «Установить кодировку символов».

Для putty: Конфигурация -> Окно -> Перевод -> UTF-8 (если это не работает, см. эта почта).

Запустите этот код, чтобы определить, является ли это проблемой компилятора или консоли:

public static void main(String[] args) throws Exception {
    String s = "¿";
    printHex(Charset.defaultCharset(), s);

    Charset utf8 = Charset.forName("UTF-8");
    printHex(utf8, s);
}

public static void printHex(Charset encoding, String s)
        throws UnsupportedEncodingException {
    System.out.print(encoding + "\t" + s + "\t");

    byte[] barr = s.getBytes(encoding);
    for (int i = 0; i < barr.length; i++) {
        int n = barr[i] & 0xFF;
        String hex = Integer.toHexString(n);
        if (hex.length() == 1) {
            System.out.print('0');
        }
        System.out.print(hex);
    }
    System.out.println();
}

Если закодированные байты для UTF-8 различны на каждой платформе (это должно быть c2bf), это проблема компилятора.

Если это проблема компилятора, замените «¿» на "\u0000".

Трудно точно узнать, какие байты содержит ваш исходный код или строку, к которой вызывается getBytes(), из-за кодировок вашего редактора и компилятора.

Можете ли вы создать короткую, но полную программу, содержащую только ASCII (и соответствующий экранирующий \uxxxx в строке), которая по-прежнему показывает проблему?

Я подозреваю, что проблема вполне может быть связана с выводом консоли в Windows или Linux, но было бы хорошо сначала получить воспроизводимую программу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top