- Wrong encoding for Postgresql messages in JDBC
- 1 Answer 1
- Как решить проблему с кодировкой в java проекте когда он в utf, а данные в win1251?
- Как решить проблему с кодировкой в vagrant?
- not correct show problem of connection #594
- Comments
- ayanprog commented Jun 27, 2016
- davecramer commented Jun 27, 2016
- vlsi commented Jun 27, 2016
- vlsi commented Aug 9, 2016
- Откуда в Java всплывают проблемы с кодировками и возможная причина падения марсианского зонда
Wrong encoding for Postgresql messages in JDBC
I have an application written in Java that connects to a Postgresql 9.3 database.
- The database I’m connecting to is created with UTF-8 enconding.
- The locale for the server where the database is installed is es-uy.UTF-8.
- All the information submitted from the application (web app running in Tomcat 7) is also in UTF-8.
Everything works according to the encoding settings except the JDBC exception messages. If I try to connect to the database with a wrong password I get:
If I try the same from psql or pgadmin I get the message with the correct encoding:
What is wrong here?
1 Answer 1
It looks like PgJDBC sets the client encoding once it’s authenticated and connected, not in the protocol startup packet. So the server doesn’t know the encoding PgJDBC expects and uses its default encoding — but PgJDBC must be ignoring the server’s notification about the server encoding.
That’s clearly a bug; I’ll chase it up if time permits.
It’s possible that I have the protocol flow order wrong here, though. I think the startup packet carries the encoding and is sent pre-auth. If I’m wrong then this is a protocol issue that requires a protocol rev to fix — not quick or simple.
(On a side note, PostgreSQL also mixes different text encodings in its log files, creating a horrible mess, because it emits log messages to the logs in the client_encoding . I’ve looked at fixing this before but there’s been resistance to what I see as the only possible fixes — a log file per database and logging in the database default encoding, or preferably just logging everything in utf-8).
Как решить проблему с кодировкой в java проекте когда он в utf, а данные в win1251?
Проблема проявляется только, если запускать проект в linux(ubutu, netbeans, если это важно).
База firebird запущена в windows, если проект запущен так же в windows, то данные из базы отображаются «корректно», если в linux, то — «кракозябрами».
В настройках jdbc «везде» стоит utf8(изменение настроек на win1251 не влияют на результат), данные в базе win1251.
Если приложение в netbeans(с теми же настройками) запущено в windows всё корректно.
Условие:
Изменить кодировку в базе нельзя.
- Вопрос задан более трёх лет назад
- 7848 просмотров
Так вот я испробовал много различных вариантов указания кодировки и не только в данном конфиге, и случайно наткнулся на параметр encoding, и вот именно он сработал установив его значением utf8.
Самое интересное что это решение работает при запуске проекта под linux(ubuntu), но при этом если проект запустить с этим параметром на windows, то там начинает проявляться именно та проблема с кодировкой которую я и пытался побороть и следовательно параметры после «пути до базы» приходится там удалять, а под linux ставить обратно.
Более правильное решение будет через параметры соединения, переданные через Properties
Проблем с кодировкой нет ни под Windows, ни под Linux
Как решить проблему с кодировкой в vagrant?
ACP это из древнегречeского ^W мелкомягкого такое важное слово из трех букв
https://knowledgebase.progress.com/articles/Articl.
может быть плохой идеей использовать поддержку национального языка в Vagrant, который AFAIK, который tries to be os independent .
UTF 8 это то что Ruby вероятно прожует зато Windows подавится.
для редактирования source of vagrant скрипта ничего особенно делать не надо надо только его найти:
это выполнено из гит баж
то же из под него родимого
— сохранил
У меня была аналогичная проблема и помогло решение со стека.
Конечно же Вы не нашли путь c:\HashiCorp\Vagrant\embedded\gems\gems\vagrant-1.6.3\bin\vagrant, так как у Вас версия vagrant 2.2.3 и соответственно путь: C:\HashiCorp\Vagrant\embedded\gems\2.2.3\gems\vagrant-2.2.3\bin\vagrant.
Чтобы отредактировать данный файл, я бы рекомендовал открыть его от имени администратора Windows в текстовом редакторе вроде Notepad++. Далее примерный перевод и копипаста:
1. Установите переменную окружения VAGRANT_HOME , например ‘c:\HashiCorp‘;
2. В файле C:\HashiCorp\Vagrant\embedded\gems\2.2.3\gems\vagrant-2.2.3\bin\vagrant после #!/usr/bin/env добавить две строки:
Важно Windows-1251, а не Windows-1250.
Думаю также может потребоваться перезагрузка для применения переменной окружения.
not correct show problem of connection #594
Comments
ayanprog commented Jun 27, 2016
i have problem with connection to db, with driver, console show problem with encoding with UTF-8 to windows-1251, but problem was in pg_hba.conf, i don’t add my ip to file, i spend a lot of time for find this problem, can you solve this problem, with correct show exception. Thx
IDE: Intelji Idea 16.1.1
ProgramLang: Groovy
java: 8u92
The text was updated successfully, but these errors were encountered:
davecramer commented Jun 27, 2016
Part of the problem here is that Groovy consumes the exceptions.
Can you show me your groovy code or a snippet and I’ll have a look
On 27 June 2016 at 07:54, ayanprog notifications@github.com wrote:
i have problem with connection to db, with driver, console show problem
with encoding with UTF-8 to windows-1251, but problem was in pg_hba.conf, i
don’t add my ip to file, i spend a lot of time for find this problem, can
you solve this problem, with correct show exception. Thx
IDE: Intelji Idea 16.1.1
ProgramLang: Groovy
java: 8u92
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#594, or mute the thread
https://github.com/notifications/unsubscribe/AAYz9j44qHxGezh7rOf8njasb3LL-cQBks5qP7oLgaJpZM4I_BMF
.
vlsi commented Jun 27, 2016
@davecramer , I think this is our well-known «backend does not send connection error in utf8» issue.
vlsi commented Aug 9, 2016
I’ve implemented a fix on top of #618.
pt_BR.ISO8859-1: org.postgresql.util.PSQLException: FATAL: banco de dados «tst» não existe (pgjdbc: autodetected server-encoding to be ISO8859_1, if the message is not readable, please check database logs and/or host, port, dbname, user, password, pg_hba.conf)
ru_RU.CP1251: org.postgresql.util.PSQLException: ВАЖНО: база данных «tst» не существует (pgjdbc: autodetected server-encoding to be Cp1251, if the message is not readable, please check database logs and/or host, port, dbname, user, password, pg_hba.conf)
ja_JP.eucJP: org.postgresql.util.PSQLException: FATAL: データベース»tst»は存在しません (pgjdbc: autodetected server-encoding to be EUC_JP, if the message is not readable, please check database logs and/or host, port, dbname, user, password, pg_hba.conf)
fr_BE.ISO8859-15: org.postgresql.util.PSQLException: FATAL: la base de données « tst » n’existe pas (pgjdbc: autodetected server-encoding to be ISO8859_1, if the message is not readable, please check database logs and/or host, port, dbname, user, password, pg_hba.conf)
Steps to reproduce:
- Download PostgreSQL sources
- ./configure —enable-nls —with-libs=/opt/local/lib —with-includes=/opt/local/include (use your libs/includes otherwise it might fail to find gettext and silently disable NLS support)
- make clean && make install
- I use the following script to recreate DB:
Откуда в Java всплывают проблемы с кодировками и возможная причина падения марсианского зонда
Планета Марс уже не первый год населена роботами. То тут, то там появляются беспилотные электрокары и летающие дроны, а в программах, написанных на Java, с завидной регулярностью всплывают проблемы с кодировками.
Хочу поделиться своими мыслями о том, почему это происходит.
Предположим, у нас есть файл, в котором хранится нужный нам текст. Чтобы поработать с этим текстом в Java нам нужно загнать данные в String. Как это сделать?
Обратите внимание, что для чтения файла недостаточно просто знать его имя. Нужно еще знать, в какой кодировке в нем находятся данные. Двоичное представление символов в памяти Java-машины и в файле на жестком диске практически никогда не совпадает, поэтому нельзя просто взять и скопировать данные из файла в строку. Сначала нужно получить последовательность байт, а уже потом произвести преобразование в последовательность символов. В приведенном примере это делает класс InputStreamReader.
Код получается достаточно громоздким при том, что необходимость в преобразовании из байтов в символы и обратно возникает очень часто. В связи с этим логичным было бы предоставить разработчику вспомомогательные функции и классы, облегчающие работу по перекодировке. Что для этого сделали разработчики Java? Они завели функции, которые не требуют указания кодировки. Например, класс InputStreamReader имеет конструктор с одним параметром типа InputStream.
Стало чуть попроще. Но здесь разработчики Java закопали серьезные грабли. В качестве кодировки для преобразования данных они использовали так называемый «default character encoding».
Default charset устанавливается Java-машиной один раз при старте на основании данных взятых из операционной системы и сохраняется для информационных целей в системном свойстве file.encoding. В связи с этим возникают следующие проблемы.
- Кодировка по умолчанию — это глобальный параметр. Нельзя установить для одних классов или функций одну кодировку, а для других — другую.
- Кодировку по умолчанию нельзя изменить во время выполнения программы.
- Кодировка по умолчанию зависит от окружения, поэтому нельзя заранее знать, какая она будет.
- Поведение методов, зависящих от кодировки по умолчанию, нельзя надежно покрыть тестами, потому что кодировок достаточно много, и множество их значений может расширяться. Может выйти какая-нибудь новая ОС с кодировкой типа UTF-48, и все тесты на ней окажутся бесполезными.
- При возникновении ошибок приходится анализировать больше кода, чтобы узнать, какую именно кодировку использовала та или иная функция.
- Поведение JVM в случае изменения окружения после старта становится непредсказуемо.
Но главное — это то, что от разработчика скрывается важный аспект работы программы, и он может просто не заметить, что использовал функцию, которая в разном окружении будет работать по-разному. Класс FileReader вообще не содержит функций, которые позволяют указать кодировку, хотя сам класс логичен и удобен, поэтому он стимулирует пользователя на создание платформозависимого кода.
Из-за этого происходят удивительные вещи. Например, программа может неправильно открыть файл, который ранее сама же создала.
Или, скажем, есть у нас XML-файл, у которого в заголовке написано encoding=«UTF-8», но в Java-программе этот файл открывается при помощи класса FileReader, и привет. Где-то откроется нормально, а где-то нет.
Особенно ярко проблема file.encoding проявляется в Windows. В ней Java в качестве кодировки по умолчанию использует ANSI-кодировку, которая для России равна Cp1251. В самой Windows говорится, что «этот параметр задает язык для отображения текста в программах, не поддерживающих Юникод». При чем здесь Java, которая изначально задумывалась для полной поддержки Юникода, непонятно, ведь для Windows родная кодировка — UTF-16LE, начиная где-то с Windows 95, за 3 года до выхода 1-й Java.
Так что если вы сохранили при помощи Java-программы файл у себя на компьютере и отправили его вашему коллеге в Европу, то получатель при помощи той же программы может и не суметь открыть его, даже если версия операционной системы у него такая же как и у вас. А когда вы переедете с Windows на Mac или Linux, то вы уже и сами свои файлы можете не прочитать.
А ведь еще есть Windows консоль, которая работает в OEM-кодировке. Все мы наблюдали, как вплоть до Java 1.7 любой вывод русского текста в черном окне при помощи System.out выдавал крокозябры. Это тоже результат использования функций, основанных на default character encoding.
Я у себя проблему кодировок в Java решаю следующим образом:
- Всегда запускаю Java с параметром -Dfile.encoding=UTF-8. Это позволяет убрать зависимость от окружения, делает поведение программ детерминированным и совместимым с большинством операционных систем.
- При тестировании своих программ обязательно делаю тесты с нестандартной (несовместимой с ASCII) кодировкой по умолчанию. Это позволяет отловить библиотеки, которые пользуются классами типа FileReader. При обнаружении таких библиотек стараюсь их не использовать, потому что, во-первых, с кодировками обязательно будут проблемы, а во-вторых, качество кода в таких библиотеках вызывает серьезные сомнения. Обычно я запускаю java с параметром -Dfile.encoding=UTF-32BE, чтобы уж наверняка.
Это не дает стопроцентной гарантии от проблем, потому что есть же еще и лаунчеры, которые запускают Java в отдельном процессе с теми параметрами, которые считают нужными. Например, так делали многие плагины к анту. Сам ант работал с file.encoding=UTF-8, но какой-нибудь генератор кода, вызываемый плагином, работал с кодировкой по умолчанию, и получалась обычная каша из разных кодировок.
По идее, со временем код должен становиться более качественным, программы более надежными, форматы более стандартизованными. Однако этого не происходит. Вместо этого наблюдается всплеск ошибок с кодировками в Java-программах. Видимо, это связано с тем, что в мир Java иммигрировали люди, не привыкшие решать проблему кодировок. Скажем, в C# по умолчанию применяется кодировка UTF-8, поэтому разработчик, переехавший с C#, вполне разумно считает, что InputStreamReader по умолчанию использует эту же кодировку, и не вдается в детали его реализации.
Недавно наткнулся на подобную ошибку в maven-scr-plugin.
Но настоящее удивление пришлось испытать при переезде на восьмерку. Тесты показали, что проблема с кодировкой затесалась в JDK.
На девятке не воспроизводится, видимо, там уже починили.
Поискав по базе ошибок, я нашел еще одну недавно закрытую ошибку, связанную с теми же самыми функциями. И что характерно, их даже исправляют не совсем правильно. Коллеги забывают, что для стандартных кодировок, начиная с Java 7, следует использовать константы из класса StandardCharsets. Так что впереди, к сожалению, нас ждет еще масса сюрпризов.
Запустив grep по исходникам JDK, я нашел десятки мест, где используются платформозависимые функции. Все они будут работать некорректно в окружении, где родная кодировка, несовместима с ASCII. Например, класс Currency, хотя казалось бы, уж этот-то класс должен учитывать все аспекты локализации.
Когда некоторые функции начинают создавать проблемы, и для них существует адекватная альтернатива, давно известно, что нужно делать. Нужно отметить эти функции как устаревшие и указать, на что их следует заменить. Это хорошо зарекомендовавший себя механизм deprecation, который даже планируют развивать.
Я считаю, что функции, зависящие от кодировки по умолчанию, надо обозначить устаревшими, тем более, что их не так уж и много:
Функция | На что заменить |
---|---|
Charset.defaultCharset() | удалить |
FileReader.FileReader(String) | FileReader.FileReader(String, Charset) |
FileReader.FileReader(File) | FileReader.FileReader(File, Charset) |
FileReader.FileReader(FileDescriptor) | FileReader.FileReader(FileDescriptor, Charset) |
InputStreamReader.InputStreamReader (InputStream) | InputStreamReader.InputStreamReader (InputStream, Charset) |
FileWriter.FileWriter(String) | FileWriter.FileWriter(String, Charset) |
FileWriter.FileWriter(String, boolean) | FileWriter.FileWriter(String, boolean, Charset) |
FileWriter.FileWriter(File) | FileWriter.FileWriter(File, Charset) |
FileWriter.FileWriter(File, boolean) | FileWriter.FileWriter(File, boolean, Charset) |
FileWriter.FileWriter(FileDescriptor) | FileWriter.FileWriter(FileDescriptor, Charset) |
OutputStreamWriter.OutputStreamWriter (OutputStream) | OutputStreamWriter.OutputStreamWriter (OutputStream, Charset) |
String.String(byte[]) | String.String(byte[], Charset) |
String.String(byte[], int, int) | String.String(byte[], int, int, Charset) |
String.getBytes() | String.getBytes(Charset) |
Да, а что там с космическим аппаратом на Марсе?
Часть программного обеспечения для марсианского зонда Скиапарелли написали на Java, на актуальной в то время версии 1.7. Запустили изделие весной, и путь к месту назначения составил полгода. Пока он летел, в Европейском космическом агентстве обновили JDK.
Ну а что? Разработка софта для нынешней миссии завершена, надо делать ПО уже для следующей, а мы все еще на семерке сидим. НАСА и Роскосмос уже давно на восьмерку перешли, а там лямбды, стримы, интерфейсные методы по умолчанию, новый сборщик мусора, и вообще.
Обновились и перед посадкой отправили на космический аппарат управляющую команду не в той кодировке, в которой он ожидал.