Unmappable character 0x98 for encoding windows 1251 intellij idea

I have a problem with the assembly of the project:

D:…\Main.java:112: error: unmappable character (0x98) for encoding
windows-1251
robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();

This error in line:
robot.getBrowserControl().findElement(By.xpath("//div[.='НАПИСАТЬ']")).click();

Images:
error, IDEA settings . Ths bottom-right is selected UTF-8. I’m not sure, but maybe it’s like the symbol «И»

img errors

This my gradle file

plugins {
    id 'java'
}

group 'ru.grbi3yh.processthesefiles'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

jar {
    baseName = 'ProcessthFiles'
}


apply plugin: 'application'

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '2.41.0'
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.7'
}

I have a problem with the assembly of the project:

D:…\Main.java:112: error: unmappable character (0x98) for encoding
windows-1251
robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();

This error in line:
robot.getBrowserControl().findElement(By.xpath("//div[.='НАПИСАТЬ']")).click();

Images:
error, IDEA settings . Ths bottom-right is selected UTF-8. I’m not sure, but maybe it’s like the symbol «И»

img errors

This my gradle file

plugins {
    id 'java'
}

group 'ru.grbi3yh.processthesefiles'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

jar {
    baseName = 'ProcessthFiles'
}


apply plugin: 'application'

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '2.41.0'
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.7'
}

У меня проблема со сборкой проекта:

D:… \ Main.java:112: ошибка: не отображаемый символ (0x98) для кодирования windows-1251
. Robot.getBrowserControl() findElement(By.xpath(«// DIV [=’НАПИСАТЬ.]»)) Нажмите ().

Эта ошибка в строке:robot.getBrowserControl().findElement(By.xpath("//div[.='НАПИСАТЬ']")).click();

Изображения: ошибка, настройки IDEA. Это справа внизу выбран UTF-8. Я не уверен, но, возможно, это похоже на символ «И»

ошибки img

Это мой подлый файл

plugins {
    id 'java'
}

group 'ru.grbi3yh.processthesefiles'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

jar {
    baseName = 'ProcessthFiles'
}


apply plugin: 'application'

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '2.41.0'
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.7'
}

I have a problem with the assembly of the project:

D:…\Main.java:112: error: unmappable character (0x98) for encoding
windows-1251
robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();

This error in line:
robot.getBrowserControl().findElement(By.xpath("//div[.='НАПИСАТЬ']")).click();

Images:
error, IDEA settings . Ths bottom-right is selected UTF-8. I’m not sure, but maybe it’s like the symbol «И»

img errors

This my gradle file

plugins {
    id 'java'
}

group 'ru.grbi3yh.processthesefiles'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

jar {
    baseName = 'ProcessthFiles'
}


apply plugin: 'application'

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '2.41.0'
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.7'
}

Setting encoding option for Java compilation should help:

compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'

As an alternative way to solve this error:

«error: unmappable character (0x98) for encoding windows-1251»

you can also change the default encoding inside Custom VM Options...:

enter image description here

by adding, e.g.:

-Dfile.encoding=UTF-8

Help | Edit Custom VM Options, then restart IntelliJ IDEA.

Последнее изменение: 17 октября 2012г.

Честно сказать, эта статья тоже из серии «ликбеза» – я считал, что об этом должны знать все.
Практика показывает, что я ошибался. Долго думал, куда бы этот материал добавить – то ли действительно
в статью «Ликбез», то ли в первую часть
«Вавилонского столпотворения». В итоге решил вынести в отдельную статью.

Вавилонское столпотворение. Часть 4. Проза жизни: компиляция и вывод в консоль

Итак, речь у нас пойдет о таких, казалось бы, примитивных процессах, как компиляция и вывод в консоль. Крайне
рекомендую ознакомиться со статьями «Ликбез» и
«Вавилонское столпотворение. Часть 1. Кодировки» – это необходимо для понимания данного
материала. По сложности же кода дальше уровня «Hello, World» мы не пойдем.

Компиляция «в лоб»

Для начала простое упражнение. Возьмите вот этот файл –
HelloWorldUTF8.java – если у вас Windows, и вот этот –
HelloWorldCp866.java – если у вас Linux или Mac. Скомпилируйте и запустите (все команды я привожу
для Windows):

javac -cp . -d . HelloWorldUTF8.java
java -cp . test.HelloWorldUTF8

Надеюсь, вы понимаете, что делают эти команды. Если нет – читайте вот это: «Ликбез».

В свой хрустальный шар я вижу, что в консоли у вас ничего хорошего. Во-первых, под Linux-ом я ожидаю кучу
предупреждений еще на стадии компиляции – 8 штук. Во-вторых, при выполнении у меня (под Windows)
– вот так:

╨Ч╨┤╤А╨░╨▓╤Б╤В╨▓╤Г╨╣, ╨Ь╨╕╤А!

Под Linux должны быть прямоугольнички вместо букв.

Теперь поменяйтесь – возьмите файл, который я предназначил для другой операционки. И то же самое
– скомпилируйте и запустите:

javac -cp . -d . HelloWorldCp866.java
java -cp . test.HelloWorldCp866

Вот так уже намного лучше. К сожалению, не могу ручаться, что в Linux тоже все хорошо, ибо настраивается эта
ОС по-разному. Но при стандартной настройке должен быть виден нормальный русский текст:

Здравствуй, Мир!

Упражнение окончено.

Что можно из него вынести? Основное, что мы увидели – результат компиляции зависит от операционной
системы. Что нас, понятное дело, устраивать не может.

Но и это еще не все. Вот то, что получилось при компиляции (необходимая версия Java – 6.0+): test_windows.zip и test_linux.zip. Запустим это
безобразие на других системах, отличных от той, где они компилировались. Содержимое
test_windows.zip
, запущенное под Linux, дает такой результат:

$ java -cp . test.HelloWorldUTF8
Здравствуй, Мир!
$ java -cp . test.HelloWorldCp866
‡¤а ўбвўг©, ЊЁа!

Ну и код из test_linux.zip под windows дает вот что:

java -cp . test.HelloWorldUTF8
╟фЁртёЄтєщ, ╠шЁ!
java -cp . test.HelloWorldCp866
??????, ???!

То есть – во всех случаях бредятина и ничего похожего на то, что было под другой OС. Никакой
переносимости. Что нас тоже никак не может устраивать.

В общем, ситуация ясна. Имеется проблема. Надо понять, как ее решать. А для этого необходимо понимание
происходящего.

Что происходит?

Для начала я открою страшную тайну. В разных системах используются разные кодировки по умолчанию. В Windows
это Cp1251, в Linux – как правило, UTF-8. Приведенные мной
примеры рассчитаны именно на это.

Второй момент, о котором знает существенно меньшее количество разработчиков. В Windows кодировка
консоли не совпадает с кодировкой системы
! Консоль по историческим причинам имеет кодировку
Cp866, также известную под неофициальными именами DOS и OEM.

Третий момент. Компилятор при разборе исходного кода по умолчанию использует кодировку системы. В Windows
Cp1251, в Linux – UTF-8.

Четвертый момент. Посмотрите на класс java.lang.System, а точнее – на его переменную
java.lang.System.out. Она имеет тип PrintStream. Т.е. –
оперирует байтами. А следовательно, тоже использует какую-то кодировку.

И вот тут-то начинается веселье. Кодировка, используемая при выводе в консоль –
системная
! А вовсе не кодировка консоли, как можно было бы предположить. И если они не совпадают
– жди неприятностей.

Понятно? Тогда вопрос. Почему же при компиляции исходника в Cp866 под Windows и его последующем
исполнении там же мы видим нормальный текст??? Кодировки-то не совпадают!

Отчасти этот факт и побудил меня вообще написать эту статью. Недавно меня на полном серьезе убеждали в одном
из форумов, что для компиляции и нормального вывода в консоль необходимо и достаточно, чтобы исходник был
в кодировке консоли. Более того, как вы только что видели, это вроде бы действительно так. Так?

Нет. И я это сейчас продемонстрирую. Возьмем еще один исходник в Cp866, почувствуем себя
немножко логопедом, отрабатывающим шипящие, и заменим уже набившую оскомину фразу «Здравствуй,
мир!
» на более веселую – «МыШка суШек насуШила!». Вот этот исходник:
HelloWorldCp866_2.java. Как и прежде – компилируем и исполняем
(это уже только под Windows):

javac -cp . -d . HelloWorldCp866_2.java
HelloWorldCp866_2.java:6: warning: unmappable character for encoding Cp1251
        System.out.println("Мы?ка су?ек насу?ила!");
                              ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding Cp1251
        System.out.println("Мы?ка су?ек насу?ила!");
                                    ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding Cp1251
        System.out.println("Мы?ка су?ек насу?ила!");
                                            ^
3 warnings

java -cp . test.HelloWorldCp866_2
Мы?ка су?ек насу?ила!

Как вам результат?

Не звучат шипящие у пациента. Причем уже на стадии компиляции. Почему? Ма-а-аленькая подсказка. Код буквы
«Ш» – 0x98. Вам это ничего не напоминает? Мне это напоминает потерявшуюся букву «И» в статье о кодировках. У нее в составе
байтов тоже было значение 0x98.

Догадались, что произошло? Двойная ошибка. Сначала Cp866 читается как системная
Cp1251
. В нижней части они совпадают, так что программный код не повреждается. А вот верхние части
таблицы (выше 127 символов) различаются, и серьезно. В результате символы, которые после компиляции
сохраняются в байт-коде, не имеют ничего общего с тем, что было в исходнике.

Однако при выводе на консоль происходит ровно обратное. Символы с помощью кодировки Cp1251
превращаются в байты. А эти байты соответствуют Cp866. Только поэтому на консоль выводится
правильный текст.

И все было бы замечательно, если бы не отсутствие в Cp1251 символа с кодом 0x98, на
который попадает буква «Ш». Декодер встречает байт 0x98, не находит такого символа
и выдает предупреждение: unmappable character for encoding Cp1251. Буквально –
неотображаемый символ для кодировки Cp1251. А сам символ замещает на «?». Это мы уже
видели. Вот «Ш» и пропала.

И еще более показательна компиляция того же исходника под Linux:

$ javac -cp . -d . HelloWorldCp866_2.java
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                            ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                              ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                                ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                                  ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                                    ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                                     ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                                      ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                                        ^
HelloWorldCp866_2.java:6: warning: unmappable character for encoding UTF8
        System.out.println("�똪� �㘥� ���㘨��!");
                                         ^

Даже сказать нечего. Если под Windows, когда однобайтовая Cp866 расценивается как однобайтовая
же Cp1251, не отображается только «Ш», то под Linux, при попытке расценить
Cp866
как многобайтовую UTF-8, текст вообще не распознался. Вылез какой-то странный
иероглиф, результат случайного совпадения нескольких байтов со схемой кодирования UTF-8.

Думаю, вы уже понимаете и то, почему при переносе скомпилированного кода из-под Windows в Linux все перестало
работать. Байты, выводимые на консоль, соответствую Cp866. А в Linux ожидается
UTF-8
. При переносе с Linux на Windows код тоже ломается, правда, по другой причине. При компиляции
там все в порядке, ибо кодировки файла и системы совпадают (если вы помните, там нормально работал именно
UTF-8 вариант кода). А вот при выводе на консоль используется системная кодировка, отличная от
консоли.

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

Как именно надо учитывать кодировку? Очень просто.

Как это должно быть сделано

Начнем с компиляции.

У компилятора есть опция -encoding. Она позволяет указать кодировку исходника. Вот ее и надо
использовать. Попробуем на примере с шипящими. Под Windows:

javac -cp . -d . -encoding Cp866 HelloWorldCp866_2.java

java -cp . test.HelloWorldCp866_2
╠√╪ър ёє╪хъ эрёє╪шыр!

И под Linux:

$ javac -cp . -d . -encoding Cp866 HelloWorldCp866_2.java
$ java -cp . test.HelloWorldCp866_2
МыШка суШек насуШила!

Если сравнивать с предыдущим вариантом, радует уже хотя бы отсутствие предупреждений
типа unmappable character for encoding XXX – исходник прочитан корректно. Под Linux и
выполнение замечательно – кодировка консоли совпадает с системной. А вот в Windows при выполнении
по-прежнему грустная картина. Не беда, сейчас и это поправим.

Итак, для того, чтобы обеспечить правильный вывод на консоль, нужно в приложении установить кодировку этой
консоли. Делается это просто. Тип поля System.outjava.io.PrintStream.
У этого класса есть один конструктор, в который можно передать кодировку. Этот конструктор и надо
использовать для создания нового потока с правильной кодировкой над существующим System.out:

System.setOut(new java.io.PrintStream(System.out, true, "Cp866"));

И всё бы хорошо. Но в разных системах кодировки консоли разные. Потому – лучше выставить значение
кодировки через свойство виртуальной машины. При старте проверить его наличие, и если установлено –
использовать. Это средство будет универсальным. Т.е. код установки кодировки консоли получится такой:

String consoleEncoding = System.getProperty("consoleEncoding");
if (consoleEncoding != null) {
    try {
        System.setOut(new PrintStream(System.out, true, consoleEncoding));
    } catch (java.io.UnsupportedEncodingException ex) {
        System.err.println("Unsupported encoding set for console: "+consoleEncoding);
    }
}

Вот версия в кодировке Cp866, в которой всё это учтено:
HelloWorldCp866_2_ok.java. Компилируем с ключом -encoding Cp866, запускаем в различных
вариантах:

javac -cp . -d . -encoding Cp866 HelloWorldCp866_2_ok.java

java -cp . test.HelloWorldCp866_2_ok
╠√╪ър ёє╪хъ эрёє╪шыр!

java -cp . -DconsoleEncoding=C866 test.HelloWorldCp866_2_ok
Unsupported encoding set for console: C866
╠√╪ър ёє╪хъ эрёє╪шыр!

java -cp . -DconsoleEncoding=Cp866 test.HelloWorldCp866_2_ok
МыШка суШек насуШила!

Ура! Шипящие появились! А ну-ка попробуем изначальную версию в UTF-8, с добавлением кодировки консоли (HelloWorldUTF8_ok.java):

javac -cp . -d . -encoding UTF-8 HelloWorldUTF8_ok.java

java -cp . test.HelloWorldUTF8_ok
╟фЁртёЄтєщ, ╠шЁ!

java -cp . -DconsoleEncoding=Cp866 test.HelloWorldUTF8_ok
Здравствуй, Мир!

И тут при указании кодировки консоли все в порядке. В Linux же все еще проще, там даже кодировку указывать
необязательно:

$ javac -cp . -d . -encoding Cp866 HelloWorldCp866_2_ok.java
$ java -cp . test.HelloWorldCp866_2_ok
МыШка суШек насуШила!

Ну и последняя проверка – переносимость. Вот написаные и скомпилированные уже по всем правилам
test.HelloWorldCp866_2_ok и test.HelloWorldUTF8_ok:
test_ok.zip. Компиляция сделана под Windows, впрочем, тут уже никакой разницы. Запускаем под Linux:

$ java -cp . test.HelloWorldCp866_2_ok
МыШка суШек насуШила!
$ java -cp . test.HelloWorldUTF8_ok
Здравствуй, Мир!

При обратном переносе ситуация аналогичная, так что консольный вывод приводит не буду.

* * *

Вот мы и добрались до финиша. Что мы вынесли из прочитанного:

Для того, чтобы исключить проблемы с кодировками при компиляции и консольном выводе,
необходимо:

  1. В явном виде указать компилятору кодировку исходника – с помощью опции
    -encoding или же каким-либо другим способом (в ant и maven есть
    свои настройки, в средах разработки также можно указать кодировку исходников)
  2. В явном виде установить кодировку консоли с помощью вызова:
    System.setOut(new java.io.PrintStream(System.out, true, "<имя кодировки>"));

Всё то же самое применимо и к потоку System.err. С System.in, использующимся для
чтения из консоли, ситуация немного другая, это чистый java.io.InputStream, потому для учета
кодировки из System.in надо читать, оборачивая его в java.io.Reader (а точнее, в его
наследника) с указанием кодировки.

Вот теперь – совсем всё! Всем спасибо!

P.S. А для чего это?

Как-то за кадром остался один вопрос. А для чего всё это вообще надо? Я разрабатываю все под
Windows, исполняю там же. Зачем мне все эти пляски с бубном про кодировки? Один раз настроил – и
хорошо.

Так вот. Дело в современных тенденциях в разработке ПО – она становится все более и более
распределенной. И, что более важно, над одним проектом начинают работать люди, говорящие на разных языках,
работающие под разными ОС и с большой вероятностью использующие разные кодовые страницы. Так вот, чтобы не
иметь проблем с исходниками, написанными товарищем по команде – жизненно необходимо работать в одной
кодировке. Иначе коллега пишет комментарии на немецком – Cp1252 – а я не могу их прочитать,
часть символов у меня заменяется на русские буквы. Ну ладно, с немецким еще как-то, а когда комментарии на
иврите? На японском? Единая кодировка – например, UTF-8, – эту проблему решает.

А по хорошему, конечно, код вообще не должен содержать ничего, кроме нижних 127 символов
iso-8859-1
, т.е. ASCII. Тогда будет гарантия чтения исходника в любых условиях.

Вот теперь действительно всё!

P.S. Обсуждение статьи: http://skipy-ru.livejournal.com/4755.html.

В начало

  • Unknown device identifier windows 7
  • Unlocker скачать бесплатно на русском языке для windows 10 x64
  • Unlocker нет в контекстном меню windows 10
  • Unlocker для windows 10 x64 rus скачать бесплатно с официального сайта
  • Unknown command target android bulldozer windows