MySQL, UTF и русские символы

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

arriah
новенький
Сообщения: 94
Зарегистрирован: 29.07.2015 15:42:35

MySQL, UTF и русские символы

Сообщение arriah »

Привет,

знаю, тема избитая, перерыл много чего, но возникли вопросы. надеюсь поможете.

Lazarus 1.6, FPC 3.0.0

Своей софтиной цепляюсь на удаленный сервер с MySQL через MySQL56Connection, CharSet в свойствах установлен UTF8, ибо база данных в UTF8
С этим проблем не возникает, все нормально корректно отображается

Из базы выгребаю html код, который надо распарсить, с этим тоже нет проблем.
Проблема начинается с русскими символами, когда начинаешь их искать в строке..
К примеру получаю строку:
str:=<a href=ссылка>описание ссылки</a> делаю так:

Код: Выделить всё

str1:=copy(str, pos('>',str)+1,pos('</a>',str)-pos('>',str)-2);

Строка как пример, таких строк много и разные
Но результат непонятный, может быть все что угодно, но не то что надо...
Вот тут я первый раз задумался о том в какой кодировке что у меня есть :)
Ладно, это обошел удалением всего до > и после </a>

Ну а дальше вобще непонятно стало, в строке есть слово Источник - и вот по нему мне надо сделать поиск..чтобы не парсить строку со ссылкой на источник...

Код: Выделить всё

if pos('источник',str)>0 then //не обрабатывать


Пофигу мороз - условие не видно, почитал в инете, подключал и lazutf8 и LCL, пользовался и pos и UTF8pos - не помогает...

от нечего делать написал:

Код: Выделить всё

if pos('источник',str)>0 then showmessage('НАШЕЛ!!!!');


сделал выборку из базы около 50 записей сидел тыкал....
результат ошеломляющий - иногда находит слово "Источник" и показывает мне месагу, иногда не находит...заменил pos, на UTF8Pos - Тоже самое

Что делать и куда копать?
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

arriah
Бывает так, что в логике задуманного действия есть ошибка, но с ходу её не видно, потому что действие реализовано сильно сложно. Как пример:

Код: Выделить всё

str1:=copy(str, pos('>',str)+1,pos('</a>',str)-pos('>',str)-2);

Поверьте, сходу и не разберёшься... ;-)
Может быть стоило написать так?

Код: Выделить всё

Var
  p1, p2: intrger;
Begin
...
  p1:= pos('>', str)+1;
  p2:=pos('</a>', str)-p1-2;
  str1:=copy(str, p1, p2);
...
End;

И экспериментами выяснить, а правильные ли позиции символов выдаёт Вам Ваша конструкция. Согласитесь, так как я написал сделать это проще.
arriah писал(а):сделал выборку из базы около 50 записей сидел тыкал....
результат ошеломляющий - иногда находит слово "Источник" и показывает мне месагу, иногда не находит...заменил pos, на UTF8Pos - Тоже самое

А Вы читали описание к функции "pos()"? Поиск регистрозависмый. А у Вас литералы для поиска заданы с маленькой буквы, а ищете Вы слово, которое начинается с большой. Потому и результаты поиска такие интересные. ;-) Попробуйте поиск делать с преобразованием строк к какому либо одному регистру с помощью "AnsiUpperCase()" или "AnsiLowerCase()".
arriah
новенький
Сообщения: 94
Зарегистрирован: 29.07.2015 15:42:35

Сообщение arriah »

Vadim писал(а):Бывает так, что в логике задуманного действия есть ошибка, но с ходу её не видно, потому что действие реализовано сильно сложно. Как пример:
КОД: ВЫДЕЛИТЬ ВСЁ

Это понятно - тут я только как пример описал. У меня для этого написано функция, которая возвращает строку заключенную между символами, например между <a> и </a>
Источник заключен в параграф <p>Источник: домен.ру</p> - поэтому вытаскивает корректно. Но есть строки, которые <a href=домен.ру>Источник</a>, если его пропарсить тем что есть - останется только слово Источник, а в моем случае, надо вытащить ссылку на этот Источник - поэтому и пытаюсь найти данное слово в тексте.

Vadim писал(а):А Вы читали описание к функции "pos()"? Поиск регистрозависмый. А у Вас литералы для поиска заданы с маленькой буквы, а ищете Вы слово, которое начинается с большой. Потому и результаты поиска такие интересные. Попробуйте поиск делать с преобразованием строк к какому либо одному регистру с помощью "AnsiUpperCase()" или "AnsiLowerCase()".


Конечно читал. И даже где-то натыкался на упоминание что UTF8 регистронезависимый (если неошибаюсь), но как бы там ни было - провел следующий эксперимент:

1. Руками в базе удалил все, оставил слово [Источник]
Результат: не находит. Сверил длины сравнимаемых строк: Источник - 16, [Источник]-18 - оно и понятно, русские символы по два байта.

2. Руками из базы, в той записи, в которой моя софтина находит слово Источник, удалил все, оставил слово [Источник]
Результат: Слово находится, длины слов те же.

Игрался с BOM и без оного, пробовал и UTF8ToAnsi и UTF8Decode|UTF8Encode - все бестолку. Ищет только то. что он сам хочет :((

База данных - это CMC от DLE - там записи все корректные. Для пущей убедительности - проверил настройки MySQL - переменные, сравнения, сами базы - все в UTF8.

Начинаю задумывать о своих умственных способностях и о смысле жизни.
Последний раз редактировалось arriah 28.06.2016 09:51:57, всего редактировалось 1 раз.
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

arriah писал(а): И даже где-то натыкался на упоминание что UTF8 регистронезависимый (если неошибаюсь),


с чего бы это?
arriah
новенький
Сообщения: 94
Зарегистрирован: 29.07.2015 15:42:35

Сообщение arriah »

Лекс Айрин писал(а):И даже где-то натыкался на упоминание что UTF8 регистронезависимый (если неошибаюсь),


с чего бы это?

Да без понятия, читал ночью, может не так понял :)

Короче, что-то тут не так:

MySQL отдает все в UTF8. Лазарь так же в UTF8.
Сейчас от безысходности, строку из базы, которая уже в UTF8 перевел в AnsiToUTF8(str) - и все заработало... и кстати поиск регистронезависимый...

В чем прикол?
В том что винда все отображает в cp1251? А посик происходит в DBMemo1?
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

arriah, скорее, база может отдавать приведенные к одному регистру строки.

arriah писал(а):Сейчас от безысходности, строку из базы, которая уже в UTF8 перевел в AnsiToUTF8(str) - и все заработало...

значит, отдают строки в ansi.
arriah
новенький
Сообщения: 94
Зарегистрирован: 29.07.2015 15:42:35

Сообщение arriah »

SET character_set_results=UTF8 - значит база отдает в UTF-8
Длина слова Источник из базы - 16 символов, насколько я понимаю ansi - Однобайтовая кодировка, значит должно быть 8.

И потом, я и так искал

Код: Выделить всё

pos(UTF8ToAnsi('Источник'),str)>0 then
к результату не приводило, а

Код: Выделить всё

pos('Источник', AnsiToUTF8(str))>0 then

дает правильный результат...

Просто интересно что происходит в мозгах лазаря...
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

arriah писал(а):дает правильный результат...


То есть, вы пытаетесь перевести в utf8 строку которая уже находится в нем? Конечно у вас ничего не получится.
arriah
новенький
Сообщения: 94
Зарегистрирован: 29.07.2015 15:42:35

Сообщение arriah »

Лекс Айрин писал(а):То есть, вы пытаетесь перевести в utf8 строку которая уже находится в нем? Конечно у вас ничего не получится.


:) Давайте еще раз, по полочкам:

str - приехало из базы, УЖЕ в UTF-8 потому что SET character_set_results=UTF8 (SET CHARACTER SET UTF8 или SET NAMES UTF8) - MySQL 5.6

pos('Источник',str)>0 then - не работе (оба в UTF8)

pos(UTF8ToAnsi('Источник'),str)>0 then - не работает (str в UTF8, а я искомое слово из UTF8 перевожу в Ansi)

pos('Источник', AnsiToUTF8(str))>0 then - работает (str в UTF8, а я его снова перевожу в UTF8)

где логика?
azsx
энтузиаст
Сообщения: 959
Зарегистрирован: 16.11.2015 05:38:32

Сообщение azsx »

str - приехало из базы, УЖЕ в UTF-8 потому что SET character_set_results=UTF8 (SET CHARACTER SET UTF8 или SET NAMES UTF8) - MySQL 5.6

так как сам мучаюсь с сохранением страниц в разных кодировках в постгрес рискну с вами не согласиться. От того, что вы сохранили что-то в поле с кодировкой utf-8 еще не сделало этот текст utf-8. То есть для постгреса верно, там может быть и ANSI из базы.
arriah
новенький
Сообщения: 94
Зарегистрирован: 29.07.2015 15:42:35

Сообщение arriah »

azsx писал(а):так как сам мучаюсь с сохранением страниц в разных кодировках в постгрес рискну с вами не согласиться. От того, что вы сохранили что-то в поле с кодировкой utf-8 еще не сделало этот текст utf-8. То есть для постгреса верно, там может быть и ANSI из базы.

В БД не я пишу, а база заполняется из CMC DLE... но если вы правы, я сейчас проверю :)

Добавлено спустя 12 минут 33 секунды:
Вобще ничего не понял...

Не делал никаких изменией в БД, все заработало и даже pos('',str) - без всяких переконвертаций...

Я отказываюсь что-либо понимать.

Черте что...
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

вот прототипы:

Код: Выделить всё

Function  Pos (const Substr : RawByteString; const Source : RawByteString) : SizeInt;
Function  Pos (c : AnsiChar; const s : RawByteString) : SizeInt;   


Где Substr -- это искомая строка, а source строка в которой ищут.

arriah писал(а):pos(UTF8ToAnsi('Источник'),str)>0 then


Насколько я помню, UTF8ToAnsi работает с глюками -- попробуйте заменить на UTF8ToCP1251
resident
энтузиаст
Сообщения: 605
Зарегистрирован: 13.03.2013 16:58:51

Сообщение resident »

azsx писал(а):От того, что вы сохранили что-то в поле с кодировкой utf-8 еще не сделало этот текст utf-8

Странно, а у меня постгрес ругается, если (как бы сказать?) невалидный UTF-8 символ хочу записать.

arriah писал(а):Я отказываюсь что-либо понимать.
Черте что...

У меня тоже был типа того прикол. Не работал запрос постгрес. Я уж и тут тему открыл, и в инете искал и доки по постгресу. За целый день мозги отлетели, но я таки изменил запрос, что он заработал. В итоге на следующий день, все само заработало! Так же мной был упомянут черт :mrgreen:
viewtopic.php?f=31&t=11131
azsx
энтузиаст
Сообщения: 959
Зарегистрирован: 16.11.2015 05:38:32

Сообщение azsx »

и у меня ругался на некорентные символы, я их даже находил. Потом начал сперва преобразовывать получаемую строку http://wiki.freepascal.org/Theodp, затем через парамс в запрос передавать
http://www.freepascal.ru/forum/viewtopi ... 95&t=10870
Но лучше не стало, внутри если эту строку с таблицы в таблицу перевести - надо преобразовывать в utf8. Я так подозреваю, что если бы я изначально взял utf-32 то проблем бы не было. Но ваще я в кодировках ничего не понимаю.
зы
Просто напомню, в том числе и вы мне помогли в той теме :)
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

resident писал(а):В итоге на следующий день, все само заработало!

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