Греческая строка не соответствует регулярному выражению при чтении с клавиатуры
public static void main(String[] args) throws IOException {
String str1 = "ΔΞ123456";
System.out.println(str1+"-"+str1.matches("^\\p{InGreek}{2}\\d{6}")); //ΔΞ123456-true
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str2 = br.readLine(); //ΔΞ123456 same as str1.
System.out.println(str2+"-"+str2.matches("^\\p{InGreek}{2}\\d{6}")); //Ξ"Ξ�123456-false
System.out.println(str1.equals(str2)); //false
}
Эта же строка не соответствует регулярному выражению при чтении с клавиатуры.
Что вызывает эту проблему, и как мы можем это решить?
Заранее спасибо.
EDIT: я использовал System.console() для ввода и вывода.
public static void main(String[] args) throws IOException {
PrintWriter pr = System.console().writer();
String str1 = "ΔΞ123456";
pr.println(str1+"-"+str1.matches("^\\p{InGreek}{2}\\d{6}")+"-"+str1.length());
String str2 = System.console().readLine();
pr.println(str2+"-"+str2.matches("^\\p{InGreek}{2}\\d{6}")+"-"+str2.length());
pr.println("str1.equals(str2)="+str1.equals(str2));
}
Выход:
ΔΞ123456-правда-8
ΔΞ123456
ΔΞ123456-правда-8
str1.equals(str2) = TRUE
Ответы
Ответ 1
Если вы используете Windows, это может быть вызвано тем фактом, что кодировка символа консоли ( "OEM-кодовая страница" ) не совпадает с системным кодированием ( "кодовая страница ANSI" ).
InputStreamReader
без явного параметра кодирования предполагает, что входные данные должны быть в кодировке по умолчанию системы, поэтому символы, считанные с консоли, декодируются некорректно.
Чтобы правильно прочитать символы non-us-ascii в консоли Windows, вам нужно явно указать консольную кодировку при построении InputStreamReader
(номер требуемой кодовой страницы можно найти, выполнив mode con cp
в командной строке):
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in, "CP737"));
То же самое относится к выходу, вам нужно построить PrintWriter
с правильной кодировкой:
PrintWriter out = new PrintWrtier(new OutputStreamWriter(System.out, "CP737"));
Обратите внимание, что с Java 1.6 вы можете избежать этих обходных решений, используя Console
объект, полученный из System.console()
, Он обеспечивает Reader
и Writer
правильно настроенную кодировку, а также некоторые полезные методы.
Однако System.console()
возвращает null
, когда потоки перенаправляются (например, при запуске из IDE). Обходной путь для этой проблемы можно найти в ответе Макдауэлла.
См. также:
Ответ 2
Есть несколько мест, где ошибки транскодирования могут иметь место здесь.
- Убедитесь, что ваш класс компилируется правильно (вряд ли это будет проблемой в среде IDE):
- Убедитесь, что компилятор использует ту же кодировку, что и ваш редактор (т.е. если вы сохраните как UTF-8, установите компилятор для использования этой кодировки)
- Или переключитесь на экранирование в подмножество ASCII, которое большинство кодировок является надмножеством (т.е. сменит строковый литерал на
"\u0394\u039e123456"
)
- Убедитесь, что вы читаете ввод с использованием правильной кодировки:
Обратите внимание, что System.console()
возвращает null в среде IDE, но есть вещи, которые вы можете сделать с этим.
Ответ 3
Я верю в обоих случаях, и ничего не изменилось в вашем коде. (Я тестировал с помощью греческой макетной клавиатуры - я из Греции:])
Вероятно, ваша клавиатура отправляет ascii в 8859-7 ISO, а не UTF-8. Шахта отправляет UTF-8.
EDIT: я по-прежнему верю в дополнение к команде equals.
System.out.println(str1.equals(str2));
Проверьте, можете ли вы заставить его работать, изменив все на греческий в региональных вариантах (если вы используете окна).
Rundll32 Shell32.dll,Control_RunDLL Intl.cpl,,0
Если это так, вы можете действовать соответственно.. как 'axtavt' сказал
Ответ 4
Клавиатура, скорее всего, не отправит символы как UTF-8, а как кодировку по умолчанию для операционной системы.
См. также