Персонажи "æ", "ø" "æ" в 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
![введите описание изображения здесь]()