В логах моей программы появилась странная ошибка:
Враг назначен, т.е. найден, теперь будем решать, что с ним делать.
Вариант, подсказанный гуглом для подобного случая с WIN1252 "(replace((mi.complemento)::text, chr(128), 'C'::text))::character varying(400)" я реализовывать не стал - так на все подобные случаи replace'ов не напасешься... Я сразу взялся за кодировку. Проверил кодировку сервера PostgreSQL:
Проба задать свойство "client_encoding" как параметр в SpecificOptions у TUniConnection:
После вкусного обеда мне пришла свежая мысль и проблема решилась с первой попытки. Как оказалось, "ларчик просто открывался" - достаточно было перед открытием UniConnection в SpecificOptions установить параметр UseUnicode в TRUE:
P.P.S. Дадаи́зм - авангардистское течение в литературе, изобразительном искусстве, театре и кино. Зародилось во время Первой мировой войны в нейтральной Швейцарии, в Цюрихе... Дадаизм возник как реакция на последствия Первой мировой войны, жестокость которой, по мнению дадаистов, подчеркнула бессмысленность существования. Рационализм и логика объявлялись одними из главных виновников опустошающих войн и конфликтов. ©Wikipedia
Дадаизм против рационализма и логики, а значит против программирования и программистов. Совпадение?...
25.10.2019 10:01:24.523 Thread #5: character with byte sequence 0xcc 0x81 in encoding "UTF8" has no equivalent in encoding "WIN1251"Первой мыслью было, что Elasticsearch не принял данные, которые я ему передал REST-запросом. Но запустив программу под отладкой я получил эту ошибку при открытии запроса к БД PostgreSQL:
Project XYZ.exe raised exception class EPgError with message 'character with byte sequence 0xcc 0x81 in encoding "UTF8" has no equivalent in encoding "WIN1251"'Посмотрев в БД данные, я сначала из-за у-умлаут грешил на слово "Zürich". Но сохранив текст в двух вариантах в файл (UTF8 и ANSI) и сравнив их, я увидел, что разница была в "Дадаи́зм" и "Дадаи?зм". Таким образом врагом WIN1251 объявляю букву "и" с ударением!
Враг назначен, т.е. найден, теперь будем решать, что с ним делать.
Вариант, подсказанный гуглом для подобного случая с WIN1252 "(replace((mi.complemento)::text, chr(128), 'C'::text))::character varying(400)" я реализовывать не стал - так на все подобные случаи replace'ов не напасешься... Я сразу взялся за кодировку. Проверил кодировку сервера PostgreSQL:
Проверил кодировку моего подключения к PostgreSQL:SHOW server_encoding; Результат: UTF8
Очевидно, что они должны совпадать. Как задать кодировку клиента при подключении к серверу PostgreSQL? В разделе 23.3.3. Automatic Character Set Conversion Between Server and Client документации PostgreSQL написано:var qEncoding: TUniQuery; ... qEncoding.SQL.Text :='SHOW client_encoding'; qEncoding.Open; Writeln(qEncoding.Fields[0].AsString); Результат: WIN1251
Значит пробуемSET client_encoding TO 'UTF8';
Значит кодировка подключения у клиента поменялась. Запускаю программу и... опять получаю ту же ошибку :-(var dbPG: TUniConnection; ... dbPG.Open; dbPG.ExecSQL('SET client_encoding TO ''UTF8'''); qEncoding.SQL.Text :='SHOW client_encoding'; qEncoding.Open; Writeln(qEncoding.Fields[0].AsString); Результат: UTF8
Проба задать свойство "client_encoding" как параметр в SpecificOptions у TUniConnection:
приводит к новой ошибке:dbPG.SpecificOptions.Add('client_encoding=UTF8');
Project XYZ.exe raised exception class Exception with message '"client_encoding" is not a valid option name for PostgreSQL UniProvider'Дальше, пробуя различные варианты SpecificOptions, мне удалось с помощью параметра "CharSet" поменять кодировку:
Все отлично: программа запустилась, кодировка подключения у клиента стала UTF8 и программа успешно обработала данные! Но результат ее работы почему-то не понравился коллеге, который занимается front-end'ом. У него, видите ли, русский текст превратился в непонятный набор символов.dbPG.SpecificOptions.Add('CharSet=UTF8'); qEncoding.SQL.Text :='SHOW client_encoding'; qEncoding.Open; Writeln(qEncoding.Fields[0].AsString); Результат: UTF8
После вкусного обеда мне пришла свежая мысль и проблема решилась с первой попытки. Как оказалось, "ларчик просто открывался" - достаточно было перед открытием UniConnection в SpecificOptions установить параметр UseUnicode в TRUE:
P.S. TUniConnection и TUniQuery - это классы Devart Universal Data Access Components (UniDAC) для доступа к данным в различных СУБД.dbPG.SpecificOptions.Add('UseUnicode=True');
P.P.S. Дадаи́зм - авангардистское течение в литературе, изобразительном искусстве, театре и кино. Зародилось во время Первой мировой войны в нейтральной Швейцарии, в Цюрихе... Дадаизм возник как реакция на последствия Первой мировой войны, жестокость которой, по мнению дадаистов, подчеркнула бессмысленность существования. Рационализм и логика объявлялись одними из главных виновников опустошающих войн и конфликтов. ©Wikipedia
Дадаизм против рационализма и логики, а значит против программирования и программистов. Совпадение?...
Комментариев нет:
Отправить комментарий