Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы с BOM, юникод и столбец mysql типа text, PHP, MySQL, JavaScript 
:(
    Опции темы
fridkaratel
Дата 11.12.2010, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



Даже не знаю, в какой из разделов написать, потому что не знаю, с чем связана ошибка...

Итак, сразу к делу.
Таблица в БД содержит:
1. DocId        bigint(10)
2. DocTitle    varchar(100) {utf8_general_ci}
3. DocDescr    text {utf8_general_ci}
4. DocText    text {utf8_general_ci}

Сама БД также в UTF-8.
Все PHP скрипты написаны в UTF-8, сохранены как UNIX/ANSI as UTF-8 (то есть без BOM).

Суть алгоритма:
- При клике в браузере на DIV jQuery AJAX посылает запрос на сервер;
- PHP-скрипт выбирает запрошенный документ из БД и выводит его в JSON-формате. Не использую JSON-библиотек, а просто:
Код
echo '({DocId, "DocTitle", "DocDescr", "DocText"})';

- jQuery AJAX получает эти данные, потом делаю:
Код
var json = eval(json);
$(DIV).html('Id:' + json['DocId'] + '<br />Title:' + <...и так далее>)


Суть проблемы:
В случайном порядке (время от времени, но постоянно) появляются знаки вопроса, но всего один раз на всей странице.
Причём появляются всегда в разных местах, то "И" выглядит как "??", то "р" как "??", то "б" как "??".
Посмотрев в WinHEX'е, увидел, что вставляется запись BOM перед буквой, которая выглядит как ?? - из-за этого и все проблемы.

Но побороть эту проблему так и не смог...

Куда смотреть, что не так?
Вообще, какие варианты возникновения этой проблемы могут быть?

UPD:
Заметил особенность - знаки ?? появляются только в DocDescr или DocText.
В DocTitle никогда не бывает ??.
Если же на странице имеется другой текст, то там тоже всё без проблем.

UPD:
Чем можно увидеть HEX-код получаемой страницы? Вместе с заголовками и со всем, всем, всем...
А то есть подозрение, что сам jQuery портит возвращаемый результат...

Это сообщение отредактировал(а) fridkaratel - 11.12.2010, 13:11
PM   Вверх
bars80080
Дата 11.12.2010, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прапор творюет
****
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 12022
Регистрация: 5.12.2007
Где: Königsberg

Репутация: 9
Всего: 315



возможно при сохранении в БД текста, текст копируется с какого-то источника, в котором есть бом. а титлы всегда набираются вручную
PM MAIL WWW   Вверх
fridkaratel
Дата 11.12.2010, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



Думал о том, что в тексте есть BOM... Как его оттуда удалить, если он там есть? Штатными средствами можно? Или же написать PHP-скрипт...?
Думал также, может сам тип "text" в MySQL мне не подходит, может лучше в VARBINARY?
PM   Вверх
bars80080
Дата 11.12.2010, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прапор творюет
****
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 12022
Регистрация: 5.12.2007
Где: Königsberg

Репутация: 9
Всего: 315



Цитата(fridkaratel @  11.12.2010,  12:11 Найти цитируемый пост)
Думал о том, что в тексте есть BOM... Как его оттуда удалить, если он там есть? Штатными средствами можно? Или же написать PHP-скрипт...?
Думал также, может сам тип "text" в MySQL мне не подходит, может лучше в VARBINARY? 

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

однако, конечно, надо придумать серверные решения. trim() не помогает? 
тогда можно посоветовать считать с подобного текста начальный байт (байты) бома, сохранить их и проверять начале вставки:

Код

$r = mb_strstr($text, $bombytes);
if($r !== false) { $text = mb_substr($text, $length_bom); }

PM MAIL WWW   Вверх
fridkaratel
Дата 11.12.2010, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



@bars80080:
Вот только одно НО...
Если я то же самое, что вывожу в echo, записываю в файл через file_put_contents, то никакого BOM'а там нет...
Это и смущает - если BOM присутствует при выборке из базы, то почему же он не присутствует в файле?  smile 
PM   Вверх
bars80080
Дата 11.12.2010, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прапор творюет
****
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 12022
Регистрация: 5.12.2007
Где: Königsberg

Репутация: 9
Всего: 315



мистика?  smile 


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

Добавлено через 1 минуту и 8 секунд
Цитата(fridkaratel @  11.12.2010,  12:26 Найти цитируемый пост)
Если я то же самое, что вывожу в echo, записываю в файл через file_put_contents, то никакого BOM'а там нет...

можно просто посмотреть проблемную запись в БД, без записей в файл. это лишнее звено, оно только внесёт дополнительные проблемы с интерпретацией ошибки
PM MAIL WWW   Вверх
skyboy
Дата 11.12.2010, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 14
Всего: 260



это не ВОМ. ВОМ - это определенные файлы в начале файла.
у тебя проблема с кодировкой базы данных. 
set names идет первым же запросом после подключения к базе данных?
PM MAIL   Вверх
fridkaratel
Дата 11.12.2010, 19:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



@skyboy:
Код

$this->Connection = mysql_connect('localhost', 'root', '');
mysql_select_db($this->Name, $this->Connection);
$this->Query('SET CHARACTER SET utf8');
$this->Query('SET NAMES utf8');


PS: Ты имел ввиду байты smile

PSS: Перед знаками вопроса вставляется что-то типа BF EF BD (точно не помню), но таких байтов два раза вподряд, то есть BF EF BD BF EF BD.

Это сообщение отредактировал(а) fridkaratel - 11.12.2010, 19:29
PM   Вверх
skyboy
Дата 11.12.2010, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 14
Всего: 260



Цитата(fridkaratel @  11.12.2010,  18:25 Найти цитируемый пост)
$this->Query('SET CHARACTER SET utf8');

удали. не нужно.
а поля таблицы в какой кодировке?
если смотреть чем-то содержимое таблицы(phpmyadmin, например) с текстом все в порядке?
PM MAIL   Вверх
fridkaratel
Дата 11.12.2010, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



Код
CREATE TABLE IF NOT EXISTS `document` (
  `DocumentId` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `CategoryId` smallint(5) unsigned NOT NULL,
  `Title` varchar(128) NOT NULL,
  `Description` text NOT NULL,
  `Content` text NOT NULL,
  PRIMARY KEY (`DocumentId`),
  KEY `CategoryId` (`CategoryId`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9;


С текстом всё впорядке... Он даже сохраняется через file_put_contents нормально... вроде...
Просто отловить появление вопросиков тяжело,.. Они произвольно попадаются.. :(
PM   Вверх
fridkaratel
Дата 13.12.2010, 05:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



Прогнал БД через "быстронаписаный" скрипт - ничего не изменилось :(
Код
$sql = $this->DB->Select('
    DocumentId,
    Title,
    Description,
    Content
    FROM
        `document`
');
foreach ($sql as $r) {
    $Cols = array();
    foreach ($r as $k => $v) {
        $v = iconv('utf-8', 'windows-1251', $v);
        $v = iconv('windows-1251', 'utf-8', $v);
        $Cols[] = $k . '="' . $v . '"';
    }

    $this->DB->Update('
        `document`
        SET
            ' . implode(',', $Cols) . '
        WHERE
            DocumentId=' . $r['DocumentId'] . '
        LIMIT 1
    ');
}


-------------------------------------------------------

Ещё заметил, что если для генерации JSON использовать конвертирование букв в \u0240, то вопросиков нет...  smile
Просто решил попробовать класс SERVICES_JSON - что он на вопросики скажет, а он их убрал... smile
Как так - не пойму... smile

Не использую класс SERVICES_JSON, т.к. он на одну букву тратит в 3 раз больше байт...
Да и, если работать с такой строкой как \u0240\0354\0155 через PHP, то он её не понимает "по-нормальному" smile

-------------------------------------------------------

@bars80080:
А чем можно сохранить всю страницу полностью со всеми заголовками, чтобы потом посмотреть в WinHEX'е?
Чтобы остались все "невидимые" символы...

Это сообщение отредактировал(а) fridkaratel - 13.12.2010, 05:27
PM   Вверх
fridkaratel
Дата 13.12.2010, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



В-общем, получил возвращаемую сервером страницу через wget.exe.
wget сохраняет страницу как UTF-9 без BOM, в файле нигде не нашёл EF BF...


В JS-скрипте сохранил результат, получаемый через jQuery AJAX.

Бред какой-то... но вот что получается...
1я строка - часть страницы, полученной через wget.exe
2я строка - результат, полученный jQuery AJAX
81 20 D0 B0 D0 BD D1 82 EF BF BD EF BF BD D0 BF D1 80 D0 B8 D0 B3 D0 B0 D1 80 D0 BD D1 8B D0 BC 20 D0 BF D0 BE D0 BA D1 80 D1 8B D1 82 D0 B8 D0
81 20 D0 B0 D0 BD D1 82             D0 B8 D0 BF D1 80 D0 B8 D0 B3 D0 B0 D1 80 D0 BD D1 8B D0 BC 20 D0 BF D0 BE D0 BA D1 80 D1 8B D1 82 D0 B8 D0 B5 D0 BC 20


Почему?  smile

Это сообщение отредактировал(а) fridkaratel - 13.12.2010, 09:56
PM   Вверх
fridkaratel
Дата 14.12.2010, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



После терзаний и поиска причины возникновения такой "бадьи" вот что накопал...:

0. Сделал экспорт базы в файл, потом открыл в Notepad++ и пересохранил в ANSI. Потом заново его открыл и пересохранил в UTF-8 без BOM. Потом очистил БД и сделал импорт "переконвертированного" файла... smile

1. Вопросики появляются с вероятностью в 98%

2. Всегда вопросики появляются в конкретном тексте в конкретных местах. Их может не появиться с вероятностью 2% (согласно п.1)

3. При смене header('Content-Type: text/javascript') на header('Content-Type: text/plain') вопросики появляются в других местах, но всё равно действуют согласно п.1 и п.2.
При смене на header('Content-Type: text/html') вопросики появляются в новых местах... 

4. Как я писал ранее, они (якобы) не появлялись в данных, взятых из полей типа varchar... При манипуляции с header'ом они появляются и там тоже... 

5. При получении страницы не через jQuery AJAX, а через XMLHttpRequest - результат не изменился... всё те же ё... долбаные вопросики...  smile 

6. При проверке в Firefox'е вопросики не появляются...  smile . Но мне надо под Adobe AIR - а там при всех тех же манипуляциях - появляются...

7. Заметил, что эти EF BF BD вставляются как-то "непонятно". Я укорачивал текст каждый раз на 1 букву, чтобы посмотреть, когда они исчезнут...
Да, нашлась такая длина строки, при которой вопросики (и EF BF BD соответственно) не вставляются в текст...
Но закономерности так и не нашёл - везде и разная длина, и разные буквы в конце текста.

8. Заметил, что, например:
Текст в БД: "вася мыл свою красную машину"
На страницу вставляется "вася мы?? свою красную машину"
Если в БД укоротить до "вася мыл свою крас", то вопросиков не появится...

Уже неделю вожусь с этим вопросом, и так, и сяк...  smile 

PS: Пока приходится тупо перегонять русские буквы в \uABCD... Но это пока... Вариант мне этот жутко не нравится...

Это сообщение отредактировал(а) fridkaratel - 14.12.2010, 11:12
PM   Вверх
skyboy
Дата 14.12.2010, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 14
Всего: 260



может, проблема в СУБД?
проблема на продакшене или на твоем компьютере локально тоже повторяется?
PM MAIL   Вверх
fridkaratel
Дата 14.12.2010, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 221
Регистрация: 22.10.2007
Где: Error connect to MySQL Da...

Репутация: нет
Всего: нет



На локальном компьютере проблема...
В продакшн-версии ещё не проверял.

Локальный сервер:
XAMPP 1.7.2
Windows 7 Ultimate x64
MySQL 5.1.37

Чувствуется, что проблема в отдаче сервером данных... Может, в php.ini что посмотреть/поправить?

Это сообщение отредактировал(а) fridkaratel - 14.12.2010, 12:35
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Базы Данных | Следующая тема »


 




[ Время генерации скрипта: 0.0581 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.