Персонажи "æ", "ø" "æ" в Java Strings (Windows)

По какой-то причине строка, которой назначена буква å с использованием класса Scanner, не равна строке, которая назначается å с помощью "нормального" способа: String a = "å" - Почему это?

import java.util.*;

public class UTF8Test {
public static void main(String [] args) {

    String [] Norge = {"løk", "hår", "vår", "sær", "søt"};

    Scanner input = new Scanner(System.in);

    String  test = input.nextLine();  //I enter løk here
    System.out.println(test);
    System.out.println(Norge[0]);

    for(int i = 0; i < Norge.length; i++) {
        if(Norge[i].equals(test) ) {
            System.out.println("YES!!");
        }
    }
}
}

Компилятор покажет это:

LOK

LOK

l├ © к

Ответы

Ответ 1

При условии, что ваше единственное требование - использовать везде UTF-8, как указано в UTF8Test classname, тогда ваша главная ошибка заключается в том, что вы используете консоль Windows для компиляции и запуска вашей программы Java. ├© как mojibaked форма ø, а именно, предполагает, что вы использовали CP850 для компиляции файла исходного кода Java. В качестве доказательства запустите это в среде с поддержкой UTF-8:

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

Отпечатает ├©. Это, в свою очередь, настоятельно указывает на то, что вы использовали консоль Windows для компиляции файла исходного кода Java, поскольку в настоящее время это единственная обычно используемая среда, которая по умолчанию использует CP850. Однако консоль Windows имеет не UTF-8.

Когда вы сохраняете (конвертировать из символов в байты) файл исходного кода с использованием кодировки UTF-8 в текстовом редакторе, символ ø превращается в байты 0xC3 и 0xB8 (в качестве доказательства см. "UTF-8 (hex)" запись в символьной информации U + 00F8). Когда вы запускаете javac UTF8Test.java, тогда сохраненный исходный код файла UTF-8 в основном считывается (преобразовывается из байтов в символы) с использованием кодировки CP850. Байты 0xC3 и 0xB8 представляют в этой кодировке символы и © (в качестве доказательства см. компоновка кодовой страницы CP850), Это полностью объясняет вашу первоначальную проблему.

Правда, вы можете указать javac прочитать файл исходного кода, используя UTF-8 аргументом -encoding UTF-8. Тем не менее, консоль Windows полностью не поддерживает входные и выходные данные UTF-8. Когда вы перекомпилируете с помощью -encoding UTF-8, вы все равно получите выход mojibaked, потому что консоль командной строки не может правильно отображать вывод UTF-8. Я попробовал это здесь, и вместо этого я получил символ градуса:

løk
l°k

Эта проблема не может быть решена, если вы собираетесь использовать UTF-8 всюду и хотите придерживаться командной консоли Windows в качестве среды ввода-вывода. В принципе, вам нужна среда ввода-вывода с поддержкой UTF-8. Достойные IDE, такие как Eclipse и Netbeans, являются такими. Или, если вы намерены запустить его как автономную программу, поддерживающую UTF-8, использование Swing UI должно быть предпочтительнее, чем консольная консоль без GUI.

Ответ 2

По умолчанию в Windows компилятор java интерпретирует весь его исходный файл, используя "кодировку по умолчанию для платформы". В зависимости от того, в какой среде вы используете компилятор, это могут быть ISO-8859-1, CP1252, UTF-8 или любая другая кодировка.

Если используемый вами редактор фактически кодирует ваши исходные файлы java с использованием UTF-8, но компилятор читает эти исходные файлы с использованием другой кодировки, тогда содержимое всей вашей жесткокодированной строки может быть потенциально завинчено (как вы уже испытали). Чтобы устранить эту проблему, либо убедитесь, что вы сохранили исходный файл java в "кодировке по умолчанию платформы", либо настройте свой java-компилятор для интерпретации исходных файлов как UTF-8.

попробуйте вызвать ваш компилятор с помощью javac -encoding UTF-8 UTF8Test.java. Убедитесь, что вы заменили UTF-8 тем, что использует ваш редактор, чтобы сохранить исходный файл, если это необходимо.

Ответ 3

Если вы хотите иметь строковый литерал со специальным символом, вы можете попробовать использовать Unicode escape:

String [] Norge = {"l\u00F8k", "h\u00E5r", "v\u00E5r", "s\u00E6r", "s\u00F8t"};

В то время как не обязательно включать специальные символы в исходный код (по крайней мере, в java), он может в некоторых случаях вызывать проблемы с плохо настроенными редакторами, компиляторами или терминалами; Лично я избегаю использования специальных символов вообще, если могу.

Кстати, вы также можете использовать экраны Unicode в другом месте в исходном коде Java, включая комментарии javadoc и имена классов, методов и переменных.

Если вы компилируете из командной строки, вы можете настроить компилятор для приема UTF-8 с помощью параметра -encoding с UTF-8 в качестве его параметра. Например:

javac -encoding UTF-8 ...

Вы также можете найти этот вопрос полезным: Специальный символ в Java


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


EDIT: я просто попытался собрать и запустить его сам (в eclipse), и у меня не было проблемы с этим, о котором вы упоминаете. Вероятно, это проблема с вашей конкретной настройкой.

Когда я переконфигурировал его для компиляции кода как US-ASCII, он выводит l?k оба раза.

Когда я переконфигурировал его для компиляции кода как UTF-8, выход был løk и løk.

Когда я скомпилировал его как UTF-16, выход был þÿ l ø k и løk, однако я не смог скопировать пробелы в þÿ l ø k с терминала: он позволил бы мне скопировать первые два, но уйти от остальных. Вероятно, это связано с проблемой, с которой вы столкнулись - они могут быть некоторыми управляющими символами, которые испортят его в вашем случае.

Ответ 4

Если вы работаете в Eclipse, измените свою консольную кодировку, используя Меню RUN > Конфигурации запуска.. > Общая вкладка (правая сторона) > В панели кодирования > выберите Other = UTF-8


введите описание изображения здесь