Греческая строка не соответствует регулярному выражению при чтении с клавиатуры

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' сказал