Содержание
- Евгений Степанищев
- Ошибка: несопоставимый символ (0x98) для кодировки windows-1251
- Запись больших файлов во внешнюю базу данных через внешний источник данных
- Ошибка: несопоставимый символ (0x98) для кодировки windows-1251
- Ошибки Postgres
- Ошибки
- psql command not found
- ERROR: character with byte sequence 0xd0 0x9a in encoding «UTF8» has no equivalent in encoding «WIN1252»
- ERROR: database «db» is being accessed by other users
- FATAL password authentication failed for user postgres
- ERROR: could not open file «/home/user…» for reading: Permission denied
- ERROR: COPY quote must be a single one-byte character
- ERROR: date/time field value out of range
- psql: could not connect to server: No such file or directory
- pg_basebackup: could not connect to server: could not connect to server: No route to host
- Failed to stop postgresql.service: Unit postgresql.service not loaded
- ERROR: WAL level not sufficient for making an online backup
- NOTICE: WAL archiving is not enabled
Евгений Степанищев
При обыденной смене типа колонки в «Постгресе» с текстового типа на бинарный получил ошибку «ERROR: invalid input syntax for type bytea». Запрос довольно рядовой и сюрпризов я не ожидал:
Решения нагуглить не удалось, поэтому начал исследовать проблему сам. Бинарным поиском нашёл строку на которой запрос запнулся, потом так же вычислил символ. Им оказался обратный слэш. Заэкранировал его и ошибка пропала:
Всё отработало нормально, сконвертировалось, слеши получаются из базы как и ожидается — одинарными.
Дурацкий способ конвертации, конечно, гораздо правильнее использовать функцию convert_to. И костылей не понадобится, и отработает, подозреваю, быстрее.
Евгений Степанищев (bolknote.ru) 2017
Комментарий для Алекс:
Это указание типа-то (CAST) — это дурацкий способ конвертации? Тем более в базе, которую свою кодировку знает?
Евгений Степанищев (bolknote.ru) 2017
Комментарий для Алекс:
Вот, кстати, разница:
doc=# select count(convert_to(extra, ’utf8’)) from medo_sync;
ERROR: character with byte sequence 0x98 in encoding «WIN1251» has no equivalent in encoding «UTF8»
doc=# select count(replace(extra, ’’, ’\’)::BYTEA) from medo_sync;
Источник
Ошибка: несопоставимый символ (0x98) для кодировки windows-1251
У меня проблема со сборкой проекта:
D. Main.java:112: error: unmappable character (0x98) for encoding windows-1251
robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();
Эта ошибка в строке: robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();
Изображений: ошибка, Настройки IDEA. В правом нижнем углу выбран UTF-8. Не уверен, но может это похоже на символ «И»
Это мой файл Gradle
Вы пробовали переименовать элемент, чтобы в нем не использовались специальные символы?
Я бы порекомендовал вам не использовать кириллицу в именах ваших переменных / полей / чего-либо на самом деле. Вы как бы просите проблемы с кодированием таким образом.
Ребята, это не имя элемента, а его содержимое.
Не думаю, что у меня есть знания, чтобы помочь, но что такое «робот» и «By.xpath ()»? Похоже, они требуют, чтобы XPath был совместим с Windows-1251, что странно, но может быть настроено.
Пытался переименовать и скопировать слово «ЗАПИСАТЬ» из других текстов. Это не моя кириллица. Это кнопка «НАПИСАТЬ» в почте Google.
«robot» и «By.xpath ()» никак не влияют на эту ошибку. В самом классе есть комментарий разработчика и в нем есть символ «И», тоже есть ошибка. Посмотрите на изображение «ошибка»
Я понимаю. Судя по вашему скриншоту, я полагаю, вы используете Maven. Maven будет использовать набор кодировок с Maven, а не с Idea. Можете ли вы показать свою конфигурацию Maven?
@kumesana я добавил часы Gradle File
Пожалуйста, не публикуйте скриншоты вещей, которые могут быть опубликованы в виде (отформатированного в коде) текста. Отредактируйте свой вопрос и замените эти снимки экрана фактическим текстом.
Честно говоря, я не вижу в этом ничего плохого, но опять же, я очень мало верю в gradle. Попробую добавить compileJava.options.encoding = ‘UTF-8’
@kumesana я добавляю `compileJava.options.encoding = ‘UTF-8’ ‘не помогло
Проблема явно в том, что компилятор использует windows-1251 для файлов java, когда, как вы говорите, они закодированы в utf-8. Может быть, windows-1251 является кодировкой по умолчанию на вашей платформе, и поэтому gradle ее использует? К сожалению, я понятия не имею, как указать Gradle, какую кодировку использовать для файлов java.
Моя платформа Windows 10 и язык по умолчанию русский
Я не знаю, опоздал ли я с этой проблемой (почти уверен, что да), но мой совет мог бы помочь другим ребятам — проблема в кириллических символах. У меня была та же проблема, и я решил ее, сохранив файл в формате ANSI (если вы используете какой-либо текстовый редактор, например блокнот, вы можете сохранить свой файл в кодировке ANSI. Возможно, этот параметр должен быть в IDE)
Настройка параметра кодировки для компиляции Java должна помочь:
Источник
Запись больших файлов во внешнюю базу данных через внешний источник данных
Суть задания такова: необходимо в бизнес-процесс прикреплять файлы, которые должны храниться во внешней базе данных.
Решение. Есть внешний источник данных. В него с помощью строки подключения добавлена таблица Trata из базы данных СУБД PosgreSQL . В эту таблицу требуется добавлять идентификатор бизнес-процесса, название файла и сам файл. В этой таблице два поля — id_biz (Тип данных в PostgreSQL — character varying 80) и file_biz (Тип данных text). Первое поле в 1С сделано первичным ключом.
Кусок кода, который показывает добавление данных во внешнюю базу данных:
Т.е. первичный ключ записи — уникальный идентификатор бизнес-процесса + имя файла. А во второе поле записывается строка неограниченной длины, полученная вследствие перевода двоичных данных файла в строку через специальную функцию.
Так вот таким способом записываются в базу данных файлы, размер которых меньше 14 000 КБ. При записи больших файлов 1С выдает ошибку Недостаточно памяти , несмотря на то что оперативки хватает.
Как исправить эту ошибку?
Пробовал создавать в таблице поле типа данных bytea, в которое можно записать Двоичные данные. Так вот иногда при отладке с помощью точки останова данные вроде как записываются, но если в СУБД составить SQL запрос, возвращающий содержимое полей таблицы, то видно что данное поле пусто. В другом случае при записи в поле типа данных bytea 1С выдает ошибку:
<Задача.РегистрацияОбращения.Форма.ФормаЗадачи.Форма(421)>: Ошибка при вызове метода контекста (Записать)
ЗаписьВДрБазу.Записать();
по причине:
Ошибка внешней базы данных:
ошибка при выполнении запроса
по причине:
Ошибка ODBC. SQLSTATE: 22P05
Номер ошибки: 7
Описание: ERROR: character with byte sequence 0x98 in encoding «WIN1251» has no equivalent in encoding «UTF8»;
Error while executing the query
Источник
Ошибка: несопоставимый символ (0x98) для кодировки windows-1251
У меня проблема со сборкой проекта:
D. Main.java:112: error: unmappable character (0x98) for encoding windows-1251
robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();
Эта ошибка в строке: robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();
Изображений: ошибка, Настройки IDEA. В правом нижнем углу выбран UTF-8. Не уверен, но может это похоже на символ «И»
Это мой файл Gradle
Вы пробовали переименовать элемент, чтобы в нем не использовались специальные символы?
Я бы порекомендовал вам не использовать кириллицу в именах ваших переменных / полей / чего-либо на самом деле. Вы как бы просите проблемы с кодированием таким образом.
Ребята, это не имя элемента, а его содержимое.
Не думаю, что у меня есть знания, чтобы помочь, но что такое «робот» и «By.xpath ()»? Похоже, они требуют, чтобы XPath был совместим с Windows-1251, что странно, но может быть настроено.
Пытался переименовать и скопировать слово «ЗАПИСАТЬ» из других текстов. Это не моя кириллица. Это кнопка «НАПИСАТЬ» в почте Google.
«robot» и «By.xpath ()» никак не влияют на эту ошибку. В самом классе есть комментарий разработчика и в нем есть символ «И», тоже есть ошибка. Посмотрите на изображение «ошибка»
Я понимаю. Судя по вашему скриншоту, я полагаю, вы используете Maven. Maven будет использовать набор кодировок с Maven, а не с Idea. Можете ли вы показать свою конфигурацию Maven?
@kumesana я добавил часы Gradle File
Пожалуйста, не публикуйте скриншоты вещей, которые могут быть опубликованы в виде (отформатированного в коде) текста. Отредактируйте свой вопрос и замените эти снимки экрана фактическим текстом.
Честно говоря, я не вижу в этом ничего плохого, но опять же, я очень мало верю в gradle. Попробую добавить compileJava.options.encoding = ‘UTF-8’
@kumesana я добавляю `compileJava.options.encoding = ‘UTF-8’ ‘не помогло
Проблема явно в том, что компилятор использует windows-1251 для файлов java, когда, как вы говорите, они закодированы в utf-8. Может быть, windows-1251 является кодировкой по умолчанию на вашей платформе, и поэтому gradle ее использует? К сожалению, я понятия не имею, как указать Gradle, какую кодировку использовать для файлов java.
Моя платформа Windows 10 и язык по умолчанию русский
Я не знаю, опоздал ли я с этой проблемой (почти уверен, что да), но мой совет мог бы помочь другим ребятам — проблема в кириллических символах. У меня была та же проблема, и я решил ее, сохранив файл в формате ANSI (если вы используете какой-либо текстовый редактор, например блокнот, вы можете сохранить свой файл в кодировке ANSI. Возможно, этот параметр должен быть в IDE)
Настройка параметра кодировки для компиляции Java должна помочь:
Источник
Ошибки Postgres
Ошибки
psql command not found
Вы хотите запустить Postgres скрипт из bash
andrey@olegovich-10:/mnt/c/Users/olegovich$ psql -h localhost -p 5432 -U andrei
но получаете эту ошибку
-bash: psql: command not found
Это значит, что путь до Postgres не прописан в $PATH
Чтобы узнать, что прописано в $PATH достаточно сделать
/home/andrei/bin:/home/andrei/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/mnt/c/Program Files (x86)/Common Files/Oracle/Java/javapath_target_1128437:/mnt/c/ProgramData/Oracle/Java/javapath_target_5252250:/mnt/c/Windows/System32:/mnt/c/Windows:/mnt/c/Windows/System32/wbem:/mnt/c/Windows/System32/WindowsPowerShell/v1.0:/mnt/c/Program Files/OpenVPN/bin:/mnt/c/Program Files (x86)/Microsoft SQL Server/Client SDK/ODBC/130/Tools/Binn:/mnt/c/Program Files (x86)/Microsoft SQL Server/140/Tools/Binn:/mnt/c/Program Files (x86)/Microsoft SQL Server/140/DTS/Binn:/mnt/c/Program Files (x86)/Microsoft SQL Server/140/Tools/Binn/ManagementStudio:/mnt/c/Program Files/MiKTeX 2.9/miktex/bin/x64:/mnt/c/Users/andreyolegovich_ru/Documents/Software/axis2-1.6.2:/mnt/c/Users/andreyolegovich_ru/Documents/Software/axis2-1.6.2/bin:/mnt/c/Windows/System32/OpenSSH:/mnt/c/Program Files/TortoiseSVN/bin:/mnt/c/Program Files/Microsoft SQL Server/Client SDK/ODBC/130/Tools/Binn:/mnt/c/Program Files/Microsoft SQL Server/140/Tools/Binn:/mnt/c/Program Files/Microsoft SQL Server/140/DTS/Binn:/mnt/c/Program Files (x86)/Intel/Intel(R) Management Engine Components/DAL:/mnt/c/Program Files/Intel/Intel(R) Management Engine Components/DAL:/mnt/c/Program Files/TortoiseGit/bin:/mnt/c/Program Files/Git/cmd:/mnt/c/Program Files/nodejs:/mnt/c/Program Files/Intel/WiFi/bin:/mnt/c/Program Files/Common Files/Intel/WirelessCommon:/mnt/c/Program Files/PuTTY:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Continuum/anaconda3:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Continuum/anaconda3/Library/mingw-w64/bin:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Continuum/anaconda3/Library/bin:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Continuum/anaconda3/Scripts:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Programs/Python/Python36/Scripts:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Programs/Python/Python36:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/andreyolegovich_ru/AppData/Local/atom/bin:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Programs/Python/Python36-32:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Programs/Python/Python36-32/Scripts:/mnt/c/Program Files (x86)/Nmap:/mnt/c/Program Files (x86)/Mozilla Firefox:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Programs/Fiddler:/mnt/c/Program Files/JetBrains/PyCharm Community Edition 2018.3.2/bin:/mnt/c/Users/andreyolegovich_ru/AppData/Roaming/npm:/mnt/c/Program Files/Intel/WiFi/bin:/mnt/c/Program Files/Common Files/Intel/WirelessCommon:/mnt/c/Users/andreyolegovich_ru/AppData/Local/Programs/Microsoft VS Code/bin:/snap/bin
ERROR: character with byte sequence 0xd0 0x9a in encoding «UTF8»
has no equivalent in encoding «WIN1252»
Скорее всего Вы создали базу данных, и даже смогли туда что-то импортировать, например, из .csv файла.
Но сделать SELECT * FROM table; уже не получается, потому что кодировка базы и кодировка файла не совпадают.
Возможно, Вы уже попробовали явно указать SET CLIENT_ENCODING TO ‘utf8’; при импорте файла. Но так как кодировка WIN1252 — это кодировка БД, способ не сработал.
Нужно привести файл и БД к одной кодировке — пересоздайте БД в utf8, например.
Как проверить кодировки я писал выше — Проверка кодировок БД
Как указать кодировку при создании БД — Создание БД
ERROR: database «db» is being accessed by other users
Если Вы делаете DROP DATABASE db; и получаете
ERROR: database «db» is being accessed by other users
DETAIL: There are 2 other sessions using the database.
Значит где-то ещё не закрыто подключение к БД. Например, Вы открывали её через pgAdmin.
Нужно найти это подключение и закрыть
FATAL password authentication failed for user postgres
Если вы логинитесь в pgAdmin, но не помните пароль — его можно поменять через терминал
sudo su — postgres
psql
postgres=# ALTER USER postgres PASSWORD ‘новый_пароль’;
ERROR: could not open file «/home/user…» for reading: Permission denied
Если вы пытаетесь прочитать из файла, а получаете
ERROR: could not open file «/home/user/file.csv» for reading: Permission denied HINT: COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql’s copy. SQL state: 42501
Значит у postgres недостаточно прав для чтения из файла. Простое добавление прав на чтение вроде
chmod +r file.csv
Проблему, скорее всего, не решит.
Как вариант — предлагаю переместить нужный файл в директорию /tmp
cp /home/user/file.csv /tmp
ERROR: COPY quote must be a single one-byte character
Если вы пытаетесь прочитать из файла, а получаете
ERROR: COPY quote must be a single one-byte character
SQL state: 0A000
Скорее всего присутствует какой-то лишний символ в QUOTE, например
ERROR: date/time field value out of range
Если вы пытаетесь прочитать из .csv файла, а получаете
ERROR: date/time field value out of range: «» HINT: Perhaps you need a different «datestyle» setting. CONTEXT: «» SQL state: 22008
Скорее всего ваш текущий datestyle не совпадает с тем, который используется в .csv файле.
datestyle — это порядок записи даты. Может быть День — Месяц — Год (DDMMYYYY), Год — Месяц — День (YYYYMMDD) или, например американский стиль Месяц — День — Год (MMDDYYYY)
Это всё актуально если тип столбца указан как дата date. Можно изменить тип на char тогда datestyle уже не нужно настраивать.
Стилей много и если они не совпадают — получается что месяц принимает значение больше 12.
Как вариант — можно перед выполнение скрипта временно изменить свой datestyle.
Например, если нужно импортировать данные из .csv с американским стилем — перед импортом добавьте
set datestyle to «US»;
psql: could not connect to server: No such file or directory
Если вы выполнили
И получили ошибку
psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket «/var/run/postgresql/.s.PGSQL.5432»?
Очень часто данная ошибка возникает вследствии того, что не была инициализирована база данных.
Initializing database . OK
Подробнее про инициализацию базы данных PostgreSQL на примере для CentOS Linux читайте в статье
pg_basebackup: could not connect to server: could not connect to server: No route to host
Если вы пытаетесь сделать реплику
pg_basebackup -h 192.168.56.109 -U repluser -D /var/lib/pgsql/data —xlog-method=stream
pg_basebackup: could not connect to server: could not connect to server: No route to host Is the server running on host «192.168.56.109» and accepting TCP/IP connections on port 5432?
sudo firewall-cmd —zone=public —add-port=5432/tcp —permanent
sudo firewall-cmd —reload
sudo firewall-cmd —list-ports
Failed to stop postgresql.service: Unit postgresql.service not loaded
Причин может быть много но среди новичков самая распространённая — попытка остановить postgresql из под пользователя postges
Например, в моём терминале я по приглашению bash-4.2$ вижу, что зашёл как postgres
Приглашение изменится на
И затем уже можно останавливать сервер
sudo systemctl stop postgresql
sudo systemctl status postgresql
● postgresql.service — PostgreSQL database server Loaded: loaded (/usr/lib/systemd/system/postgresql.service; disabled; vendor preset: disabled) Active: inactive (dead) Jun 09 12:20:24 localhost.localdomain systemd[1]: Unit postgresql.service entered failed state. Jun 09 12:20:24 localhost.localdomain systemd[1]: postgresql.service failed. Jun 09 12:21:59 localhost.localdomain systemd[1]: Starting PostgreSQL database server. Jun 09 12:22:00 localhost.localdomain systemd[1]: Started PostgreSQL database server. Jun 10 19:10:02 localhost.localdomain systemd[1]: Stopping PostgreSQL database server. Jun 10 19:10:03 localhost.localdomain systemd[1]: Stopped PostgreSQL database server. Jun 10 22:14:18 localhost.localdomain systemd[1]: Starting PostgreSQL database server. Jun 10 22:14:19 localhost.localdomain systemd[1]: Started PostgreSQL database server. Jun 11 10:11:15 localhost.localdomain systemd[1]: Stopping PostgreSQL database server. Jun 11 10:11:16 localhost.localdomain systemd[1]: Stopped PostgreSQL database server.
ERROR: WAL level not sufficient for making an online backup
Вы хотите настроить онлайн бэкап, например с помощью команды
-bash-4.2$ psql -c «SELECT pg_start_backup(‘replbackup’);»
Но получаете ошибку
ERROR: WAL level not sufficient for making an online backup
HINT: wal_level must be set to «archive» or «hot_standby» at server start.
Нужно узнать расположение конфигурационного файла postgresql.conf
-bash-4.2$ su — postgres -c «psql -c ‘SHOW config_file;’»
Password: config_file ————————————- /var/lib/pgsql/data/postgresql.conf (1 row)
Нужно установить wal_level = hot_standby
NOTICE: WAL archiving is not enabled
Вы заканчиваете бэкап, например с помощью команды
psql -c «SELECT pg_stop_backup();»
Но получаете предупреждение
NOTICE: WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup
Источник
Дано:
При получении массива байт извне (например, через jni-буфер) необходимо преобразовать его в строку Java, с русскими буквами.
В чём сложность:
Символ «И» кодируется в UTF-8 последовательностью из двух байтов: 0xD0,0x98
. Соответственно, при чтении в кодировке windows-1251 каждый из этих байтов декодируется по схеме данной кодировке. Так вот, я обнаружил следующее – код 0x98
не определен в наборе символов windows-1251 и, соответственно, в схеме этой кодировки. Вот схема кодировки cp1251, взятая с сайта Microsoft, а вот ее описание (взято отсюда). Как вы можете видеть, код 0x98
описан как UNDEFINED
.
Проблема и решение:
Допустим откуда-то извне к нам попал массив байт, с неизвестной кодировкой. И с этим массивом надо проделать некоторые преобразования, то возможен хитрый ньюанс. Если на входе кодировка UTF-8, а в массиве есть русская буква И, то при попытке в java-коде создать строку с кодировкой windows-1251, мы получим «?»(он же — неопределённый байт) в созданной строке. При дальнейшем преобразовании в байты, этот символ просто потеряется (зачем нужны такие преобразования, я тут рассматривать не буду, но иногда такие вещи случаются ).
Немного кода :
// получаем правильную последовательность байт (то, что пришло нам извне)
byte[] bytes = «И-диотизм».getBytes(«UTF-8″);
// Создаём строку с кодировкой по умолчанию
// Напечатает «Каракули=Р?-диотизм», где видно, что один символ «?»
System.out.println(«Каракули=» + new String(bytes, «Cp1251»));
System.out.println(«Каракули=» + new String(bytes)); // аналогично
// Дальнейшее преобразование и потеря информации
String s1251_x = new String(bytes);
String xx = new String(s1251_x.getBytes(), «UTF-8″); // даже в изначально правильной кодировке
// Выведет «xx=??-диотизм,len=10»
System.out.println(«xx=» + xx + «,len=» + xx.getBytes().length);
Решение :
Единственное решение, которое (на данный момент) я знаю, это узнавать в каждом конкретном случае какая кодировка приходит на вход и создавать первую строку в соответствующей кодировке.
// Если сразу сделать так
String sUtf8 = new String(bytes, «UTF-8»);
// то и дальнейшие преобразования не потеряют информацию на входе
// Напечатает «sUtf8=И-диотизм,len=17»
System.out.println(«sUtf8=» + sUtf8 + «,len=» + bytes.length);
String s1251_2 = new String(sUtf8.getBytes(), «Cp1251»);
// Напечатает «s1251_2=И-диотизм»
System.out.println(«s1251_2=» + s1251_2);
P.S.: Я эти заметки пишу для себя, и для конкретной ситуации, которая случилась в нашем коде. О глобальном подходе к кодированию/декодированию очень понятно и хорошо написано тут : http://www.skipy.ru/technics/encodings.html
Содержание
- Error unmappable character 0x98 for encoding windows 1251
- Вавилонское столпотворение. Часть 4. Проза жизни: компиляция и вывод в консоль
- Компиляция «в лоб»
- Что происходит?
- Как это должно быть сделано
- P.S. А для чего это?
- предупреждение» unmappable character for encoding » в Java
- 10 ответов
- Ошибка: несопоставимый символ (0x98) для кодировки windows-1251
- Ошибка «Unmappable character for encoding UTF-8» (7)
- Вопрос №33704 от пользователя Konstantin Valeev в уроке «Модуль 3. Урок 1. Основы использования и создания методов в классах.», курс «Введение в Java»
Error unmappable character 0x98 for encoding windows 1251
Последнее изменение: 17 октября 2012г.
Честно сказать, эта статья тоже из серии «ликбеза» – я считал, что об этом должны знать все. Практика показывает, что я ошибался. Долго думал, куда бы этот материал добавить – то ли действительно в статью «Ликбез», то ли в первую часть «Вавилонского столпотворения». В итоге решил вынести в отдельную статью.
Вавилонское столпотворение. Часть 4. Проза жизни: компиляция и вывод в консоль
Итак, речь у нас пойдет о таких, казалось бы, примитивных процессах, как компиляция и вывод в консоль. Крайне рекомендую ознакомиться со статьями «Ликбез» и «Вавилонское столпотворение. Часть 1. Кодировки» – это необходимо для понимания данного материала. По сложности же кода дальше уровня «Hello, World» мы не пойдем.
Компиляция «в лоб»
Для начала простое упражнение. Возьмите вот этот файл – HelloWorldUTF8.java – если у вас Windows, и вот этот – HelloWorldCp866.java – если у вас Linux или Mac. Скомпилируйте и запустите (все команды я привожу для Windows):
Надеюсь, вы понимаете, что делают эти команды. Если нет – читайте вот это: «Ликбез».
В свой хрустальный шар я вижу, что в консоли у вас ничего хорошего. Во-первых, под Linux-ом я ожидаю кучу предупреждений еще на стадии компиляции – 8 штук. Во-вторых, при выполнении у меня (под Windows) – вот так:
Под Linux должны быть прямоугольнички вместо букв.
Теперь поменяйтесь – возьмите файл, который я предназначил для другой операционки. И то же самое – скомпилируйте и запустите:
Вот так уже намного лучше. К сожалению, не могу ручаться, что в Linux тоже все хорошо, ибо настраивается эта ОС по-разному. Но при стандартной настройке должен быть виден нормальный русский текст:
Что можно из него вынести? Основное, что мы увидели – результат компиляции зависит от операционной системы. Что нас, понятное дело, устраивать не может.
Ну и код из test_linux.zip под windows дает вот что:
То есть – во всех случаях бредятина и ничего похожего на то, что было под другой OС. Никакой переносимости. Что нас тоже никак не может устраивать.
В общем, ситуация ясна. Имеется проблема. Надо понять, как ее решать. А для этого необходимо понимание происходящего.
Что происходит?
И вот тут-то начинается веселье. Кодировка, используемая при выводе в консоль – системная! А вовсе не кодировка консоли, как можно было бы предположить. И если они не совпадают – жди неприятностей.
Понятно? Тогда вопрос. Почему же при компиляции исходника в Cp866 под Windows и его последующем исполнении там же мы видим нормальный текст. Кодировки-то не совпадают!
Отчасти этот факт и побудил меня вообще написать эту статью. Недавно меня на полном серьезе убеждали в одном из форумов, что для компиляции и нормального вывода в консоль необходимо и достаточно, чтобы исходник был в кодировке консоли. Более того, как вы только что видели, это вроде бы действительно так. Так?
И еще более показательна компиляция того же исходника под Linux:
Итак, к какому выводу можно придти. Кодировку надо учитывать как во время компиляции, так и при выводе на консоль. Невыполнение этого правила в любом из двух мест способно вызвать проблемы.
Как именно надо учитывать кодировку? Очень просто.
Как это должно быть сделано
Начнем с компиляции.
Если сравнивать с предыдущим вариантом, радует уже хотя бы отсутствие предупреждений типа unmappable character for encoding XXX – исходник прочитан корректно. Под Linux и выполнение замечательно – кодировка консоли совпадает с системной. А вот в Windows при выполнении по-прежнему грустная картина. Не беда, сейчас и это поправим.
И всё бы хорошо. Но в разных системах кодировки консоли разные. Потому – лучше выставить значение кодировки через свойство виртуальной машины. При старте проверить его наличие, и если установлено – использовать. Это средство будет универсальным. Т.е. код установки кодировки консоли получится такой:
Ура! Шипящие появились! А ну-ка попробуем изначальную версию в UTF-8, с добавлением кодировки консоли (HelloWorldUTF8_ok.java):
И тут при указании кодировки консоли все в порядке. В Linux же все еще проще, там даже кодировку указывать необязательно:
Ну и последняя проверка – переносимость. Вот написаные и скомпилированные уже по всем правилам test.HelloWorldCp866_2_ok и test.HelloWorldUTF8_ok : test_ok.zip. Компиляция сделана под Windows, впрочем, тут уже никакой разницы. Запускаем под Linux:
При обратном переносе ситуация аналогичная, так что консольный вывод приводит не буду.
Вот мы и добрались до финиша. Что мы вынесли из прочитанного:
Для того, чтобы исключить проблемы с кодировками при компиляции и консольном выводе, необходимо:
Вот теперь – совсем всё! Всем спасибо!
P.S. А для чего это?
Как-то за кадром остался один вопрос. А для чего всё это вообще надо? Я разрабатываю все под Windows, исполняю там же. Зачем мне все эти пляски с бубном про кодировки? Один раз настроил – и хорошо. Вопрос, кстати, не праздный, мне его задавали.
Так вот. Дело в современных тенденциях в разработке ПО – она становится все более и более распределенной. И, что более важно, над одним проектом начинают работать люди, говорящие на разных языках, работающие под разными ОС и с большой вероятностью использующие разные кодовые страницы. Так вот, чтобы не иметь проблем с исходниками, написанными товарищем по команде – жизненно необходимо работать в одной кодировке. Иначе коллега пишет комментарии на немецком – Cp1252 – а я не могу их прочитать, часть символов у меня заменяется на русские буквы. Ну ладно, с немецким еще как-то, а когда комментарии на иврите? На японском? Единая кодировка – например, UTF-8, – эту проблему решает.
Источник
предупреждение» unmappable character for encoding » в Java
в настоящее время я работаю на Java-проект, который выдает следующее предупреждение при компиляции:
Я не уверен, как так будет отображать символ до даты, но он должен быть символом авторских прав и отображается в предупреждении как знак вопроса в алмазе.
стоит отметить, что символ отображается в выходном артефакте правильно, но предупреждения являются помехой, и файл, содержащий этот класс, может однажды коснуться текста редактор, который неправильно сохраняет кодировку.
Как я могу ввести этот символ в строку «copyright», чтобы компилятор был доволен, и символ сохраняется в файле без потенциальных проблем с повторным кодированием?
10 ответов
используйте формат escape «uxxxx».
по данным Википедия, символ авторского права-unicode U + 00A9, поэтому ваша строка должна гласить:
Если вы используете Maven, установить явно в конфигурации плагина компилятора, например,
все, что вам нужно сделать, это указать переменную envirnoment называется JAVA_TOOL_OPTIONS. Если вы установите для этой переменной значение-Dfile.кодировка=utf8 в, каждый раз, когда запускается JVM, он будет получать эту информацию.
большую часть времени эта ошибка компиляции происходит при компиляции файла unicode(UTF-8)
а также вы можете добавить этот параметр компиляции в свою IDE пример: Intellij idea
(Файл>настройки>компилятор Java) добавить в качестве дополнительного параметра командной строки
-кодировка : кодировка Задайте имя кодировки исходного файла, например EUC-JP и UTF-8.. Если-encoding не указан, конвертер платформы по умолчанию используемый. (DOC)
Если вы используете eclipse (Eclipse может поставить код utf8 для вас даже вы пишете символ utf8. Вы увидите обычный символ utf8 при программировании, но фон будет кодом utf8);
П. С. : это будет хорошо, если вы статическое значение в коде. Например, String test = «IIIIIııııııççççç»;
У меня была та же проблема, где индекс символов, сообщенный в сообщении об ошибке java, был неправильным. Я сузил его до символов двойной кавычки непосредственно перед сообщаемой позицией, являющейся шестнадцатеричной 094 (отмена вместо кавычки, но представленная как цитата) вместо шестнадцатеричной 022. Как только я поменялся на вариант hex 022, все было в порядке.
Если используется сборка Maven из командной строки, можно также использовать следующую команду:
Источник
Ошибка: несопоставимый символ (0x98) для кодировки windows-1251
У меня проблема со сборкой проекта:
D. Main.java:112: error: unmappable character (0x98) for encoding windows-1251
robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();
Эта ошибка в строке: robot.getBrowserControl().findElement(By.xpath(«//div[.=’НАПИСАТЬ’]»)).click();
Изображений: ошибка, Настройки IDEA. В правом нижнем углу выбран UTF-8. Не уверен, но может это похоже на символ «И»
Это мой файл Gradle
Вы пробовали переименовать элемент, чтобы в нем не использовались специальные символы?
Я бы порекомендовал вам не использовать кириллицу в именах ваших переменных / полей / чего-либо на самом деле. Вы как бы просите проблемы с кодированием таким образом.
Ребята, это не имя элемента, а его содержимое.
Не думаю, что у меня есть знания, чтобы помочь, но что такое «робот» и «By.xpath ()»? Похоже, они требуют, чтобы XPath был совместим с Windows-1251, что странно, но может быть настроено.
Пытался переименовать и скопировать слово «ЗАПИСАТЬ» из других текстов. Это не моя кириллица. Это кнопка «НАПИСАТЬ» в почте Google.
«robot» и «By.xpath ()» никак не влияют на эту ошибку. В самом классе есть комментарий разработчика и в нем есть символ «И», тоже есть ошибка. Посмотрите на изображение «ошибка»
Я понимаю. Судя по вашему скриншоту, я полагаю, вы используете Maven. Maven будет использовать набор кодировок с Maven, а не с Idea. Можете ли вы показать свою конфигурацию Maven?
@kumesana я добавил часы Gradle File
Пожалуйста, не публикуйте скриншоты вещей, которые могут быть опубликованы в виде (отформатированного в коде) текста. Отредактируйте свой вопрос и замените эти снимки экрана фактическим текстом.
Честно говоря, я не вижу в этом ничего плохого, но опять же, я очень мало верю в gradle. Попробую добавить compileJava.options.encoding = ‘UTF-8’
@kumesana я добавляю `compileJava.options.encoding = ‘UTF-8’ ‘не помогло
Проблема явно в том, что компилятор использует windows-1251 для файлов java, когда, как вы говорите, они закодированы в utf-8. Может быть, windows-1251 является кодировкой по умолчанию на вашей платформе, и поэтому gradle ее использует? К сожалению, я понятия не имею, как указать Gradle, какую кодировку использовать для файлов java.
Моя платформа Windows 10 и язык по умолчанию русский
Источник
Ошибка «Unmappable character for encoding UTF-8» (7)
«error: unmappable character for encoding UTF-8» означает, что java нашел символ, который не отображается в UTF-8. Следовательно, откройте файл в редакторе и установите кодировку символов в UTF-8. Вы должны иметь возможность найти символ, который не представлен в UTF-8. Снять этот символ и перекомпилировать.
Я получаю ошибку компиляции по следующему методу.
Как я могу это исправить? Благодарю.
Скомпилируйте и разворачивайте код.
Компилятор Java предполагает, что ваш вход кодируется в кодировке UTF-8 либо потому, что вы указали его, либо потому, что это ваша стандартная кодировка платформы.
Компилятор использует кодировку символов UTF-8 для чтения вашего исходного файла. Но файл должен был быть написан редактором с использованием другой кодировки. Откройте файл в редакторе, установленном в кодировку UTF-8, исправьте метку кавычки и сохраните ее снова.
Спасибо Michael Konietzka ( https://.com/a/4996583/1019307 ) за ваш ответ.
Я сделал это в Eclipse / STS:
что приводит к следующему результату (испорченному из-за разметки):
Чтобы исправить это, сохраните исходные файлы с кодировкой UTF-8.
Я собираюсь создать сервер сборки CI в ящике Linux для устаревшей системы, запущенной в 2000 году. Существует раздел, в котором создается PDF-файл, который содержит символы, отличные от UTF8. Мы находимся в заключительных шагах релиза, поэтому я не могу заменить героев, дающих мне горя, но по причинам Dilbertesque я не могу ждать неделю, чтобы решить эту проблему после выпуска. К счастью, команда «javac» в Ant имеет параметр «encoding».
Источник
Вопрос №33704 от пользователя Konstantin Valeev в уроке «Модуль 3. Урок 1. Основы использования и создания методов в классах.», курс «Введение в Java»
Было бы хорошо увидеть пример того, что Вы пытаетесь скомпилировать.
Java нормально работает с кириллицей, как с текстом. А вот код должен быть обязательно латиницей. Попробуйте сменить кодировку файла, который пытаетесь скомпилировать, в редакторе, до того как скормите его javac-у.
Компилирую код, который вы приложили к уроку, ничего кроме:
Sublime пишет что кодировка UTF-8.
У меня этот код компилится и под Windows и под Ubuntu.
А какая версия ОС у вас (какого года)? Какая версия java, javac?
Microsoft Windows 10 Enterprise 10.0.17763 N/A Build 17763
java version «1.8.0_221» Java(TM) SE Runtime Environment (build 1.8.0_221-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
Это определенно проблема в самой операционной системе.
Скорее всего в настройках региональных стандартов нужно выставить «язык программ, не поддерживающих Юникод» с Английского на Русский. Но придется менять язык системы.
Есть возможность исправить проблему кодировки через реестр:
Запускаем regedit (Win + R —> regedit) и по пути HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlNlsCodePage находим ключ ACP в котором нужно поменять значение (value data) с 1252 на 1251.
Потребуется перезагрузка системы.
UPD. В зависимости от качества дистрибутива системы, возможно, поможет установка дополнительных языковых пакетов через магазин или просто в настройках системы.
Сергей Алексеенко, у меня в реестре всё так, как вы рекомендуете и в настройках региональных стандартов тоже, однако проблему это не решает. Ошибка есть.
Не знаю, в чём было дело, но конкретно в моём случае, компилятору не нравилась заглавная буква И. Причем не важно, в каком месте я её ставлю. Исправил на маленькую «и» и всё скомпилировалось.
Очевидно javac ничего не знает про «и» в верхнем регистре в UTF-8. И этот баг с буквой «И» я не смог победить в javac.
Но нашел еще два способа как обойти в общем проблему с кодировкой:
В результате применения второго способа у меня пропала козябра в WindowsPowerShell, при исполнении данного кода. Побочных ефектов в других программах я пока не заметил.
Андрей Абрашкин, первый способ тоже должен работать. Нужно внимательно произвести описанные действия. Там важно сохранять файл на каждом этапе. Можно еще включить отображение кодировок в Sublime: в настройках пользователя добавить «show_encoding»: true. И ни в коем случае не впечатывать туда «И». ))
Сергей Алексеенко, ааа, не впечатывать «И»))) Тогда да, тогда сорри, недопонял, тогда всё работает! Без «И»)) Честно говоря, Sublime мне как-то не зашёл. Давно правда это было. Может сейчас изменится мнение, но я пока на Notepad++ и AkelPad сижу. В Npp вкладки и подсветка синтаксиса. В AkelPad удобство смены кодировки и работы с текстом больших размеров. Надо бы снова присмотреться к Sublime.
Источник
Платные услуги для вашего проекта
- Консалтинг и техническая поддержка
Запросы в рамках коммерческой поддержки имеют гарантированное время ответа
- Разработка на заказ
Предоставляем разработку полностью нашими рабочими ресурсами или участвуем в создании вашего проекта
- Обучение
Для быстрого и всестороннего освоения особенностей платформы, чтобы повысить продуктивность вашей команды
Haulmont
мы разрабатываем современные корпоративные решения
-
Эксперты в области разработки корпоративного ПО
-
Создатели CUBA Platform
-
Компания основана в 2008
-
300+
разработчиков
-
400+
проектов
-
Клиенты в
60+
странах
Konstantin_v 1 / 1 / 1 Регистрация: 29.05.2014 Сообщений: 20 |
||||||||
1 |
||||||||
Вывод «И» и ошибка в комментарии31.07.2014, 23:56. Показов 5571. Ответов 2 Метки нет (Все метки)
Для демонстрации проблемы привожу 2 простых класса:
При запуске класса t в IDEA выводится предсказуемый результат, но если попытаться скомпилировать t.java в консоли, то вылетают ошибки, причем одна из них в комментарии(!): Прошу помочь разобраться отчего так происходит.
__________________
0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
31.07.2014, 23:56 |
Ответы с готовыми решениями: Как написать регулярное выражение для выдергивания английских букв и символов: «+», «,», «:», «-«, » «, «!», «?» и «.» В зависимости от времени года «весна», «лето», «осень», «зима» определить погоду «тепло», «жарко», «холодно», «очень холодно» Классы «Работник», «Календарь», «Оплата труда за месяц». Вывод табеля рабочего времени сотрудника Получить значение из {«text1″:»val1″,»text2″:»val2″,»text3»:{«text»:»val»}} 2 |
4087 / 3821 / 745 Регистрация: 18.05.2010 Сообщений: 9,331 Записей в блоге: 11 |
|
01.08.2014, 00:09 |
2 |
В какой кодировке вы сохранили java файл? Код java -encoding UTF-8 t.java
1 |
1 / 1 / 1 Регистрация: 29.05.2014 Сообщений: 20 |
|
01.08.2014, 00:23 [ТС] |
3 |
согласно Notepad++ кодировка файла UTF-8 (без ВОМ)
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
01.08.2014, 00:23 |
3 |
Последнее изменение: 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. Запустим это
безобразие на других системах, отличных от той, где они компилировались. Содержимое
, запущенное под Linux, дает такой результат:
test_windows.zip
$ 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, при попытке расценить
как многобайтовую
Cp866UTF-8
, текст вообще не распознался. Вылез какой-то странный
иероглиф, результат случайного совпадения нескольких байтов со схемой кодирования UTF-8.
Думаю, вы уже понимаете и то, почему при переносе скомпилированного кода из-под Windows в Linux все перестало
работать. Байты, выводимые на консоль, соответствую Cp866
. А в Linux ожидается
. При переносе с Linux на Windows код тоже ломается, правда, по другой причине. При компиляции
UTF-8
там все в порядке, ибо кодировки файла и системы совпадают (если вы помните, там нормально работал именно
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.out
– java.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 Здравствуй, Мир!
При обратном переносе ситуация аналогичная, так что консольный вывод приводит не буду.
* * *
Вот мы и добрались до финиша. Что мы вынесли из прочитанного:
Для того, чтобы исключить проблемы с кодировками при компиляции и консольном выводе,
необходимо:
- В явном виде указать компилятору кодировку исходника – с помощью опции
-encoding
или же каким-либо другим способом (вant
иmaven
есть
свои настройки, в средах разработки также можно указать кодировку исходников) - В явном виде установить кодировку консоли с помощью вызова:
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-1ASCII
. Тогда будет гарантия чтения исходника в любых условиях.
Вот теперь действительно всё!
P.S. Обсуждение статьи: http://skipy-ru.livejournal.com/4755.html.
В начало