Intereting Posts
Найти пользователя в Laravel по имени пользователя Определение маршрутизации по умолчанию для контроллера / действия в symfony 2 Мгновенное уведомление с использованием php / mysql, пожалуйста, дайте мне общую идею Подсчет слов в PHP Php и MySQL GROUP_CONCAT с запятой разделителя и поиск, где concat запятой Как установить переменную на странице PHP, передать ее в файл CSS и присвоить ее одному атрибуту CSS? SQLSTATE Неизвестный сервер MySQL-сервера '' (2) в Laravel PHP неправильно обрабатывает мой статический вызов Напишите в буфер вывода PHP, а затем загрузите CSV из буфера Как обрабатывать покупку для 2checkout с завитком (PHP) Как правильно уничтожить cookie сеанса? Быстрая реализация PHP-кода Aho-Corasick PHP CGI заменяет имя вызываемого файла в вызовах командной строки exec, вызывая бесконечный цикл MySQL "ERROR 1046 (3D000): не выбрана база данных" в запросе обновления Функция электронной почты php не получает электронные письма

Строки UTF-8 в базе данных MySQL перепутались после изменения конфигурации

У меня есть MySQL со строками, которые я оставил бездействующими некоторое время. Теперь, когда я снова поднял его, я заметил, что все специальные персонажи прищурены. Мой интернет-провайдер портировал сервер на другую машину, я подозреваю, что это могло произойти, когда это произошло.

База данных была заполнена скриптом PHP. Все должно было быть в UTF-8, это то, к чему настроена база данных.

Однако теперь это выглядит так:

fête

Эти четыре специальных символа должны быть одним персонажем, ê , строка должна быть fête .

Теперь похоже, что это просто перекодировано дважды, но это кажется неправильным. Эти четыре символа в шестнадцатеричном виде:

C3 83 C6 92 C3 82 C2 AA

Это очень похоже на UTF-8, поэтому, если мы его декодируем, мы получаем

C3 3F C2 AA

Это не совсем UTF-8 (из-за 3F ), но давайте расшифруем его снова:

FF AA

Это не UTF-8.

ê является EA , в UTF-8, который будет C3 AA .

Другой пример: Испанский перевернутый вопросительный знак ( ¿ ) существует как C8 83 E2 80 9A C3 82 C2 , который декодирует C3 3F 82 BF , что опять не является правильным UTF-8 (переводится в FF 82 BF ). Ожидаемый характер для ¿BF , т.е. C2 BF в правильном UTF-8.

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

(Обратите внимание: новый сервер требует, чтобы я написал mysql_set_charset("utf8"); иначе строки тоже перепутались, хотя в режиме «UTF-8 как latin1» не в этом странном виде, как показано выше).

TL; DR:

  • База данных MySQL была заполнена в UTF-8 через PHP-скрипт
  • В течение многих лет бездействующий сервер переводился.
  • Теперь символы перепутаны, см. Выше.

 C3 83 C6 92 C3 82 C2 AA 

Это очень похоже на UTF-8, поэтому, если мы его декодируем, мы получаем

 C3 3F C2 AA 

Это то, что вы получаете, если обрабатывать последовательность байтов как UTF-8, а затем кодировать ее как ISO-8859-1. 3F есть ? , который был включен в качестве замещающего символа, поскольку UTF-8 C6 92 является U + 0192 ƒ который не существует в ISO-8859-1. Но он существует в кодовой странице Windows 1252 Western European, кодировке, очень похожей на ISO-8859-1; там, это байт 0x83.

 C3 83 C2 AA 

Пройдите еще один раунд лечения-как-UTF-8-bytes-and-encode-to-cp1252, и вы получите:

 C3 AA 

который, наконец, UTF-8 для ê .

Обратите внимание, что даже если вы используете HTML-страницу, отличную от XML, явно как ISO-8859-1, браузеры фактически будут использовать кодировку cp1252 из-за неприятных исторических причин.

К сожалению, у MySQL нет кодировки cp1252; latin1 (правильно) ISO-8859-1. Таким образом, вы не сможете исправить данные, сбросив как latin1, а затем перезагрузив как utf8 (дважды). Вам придется обработать скрипт текстовым редактором, который может быть сохранен как (или, например, в file(path, 'rb').read().decode('utf-8').encode('cp1252').decode('utf-8').encode('cp1252') Python file(path, 'rb').read().decode('utf-8').encode('cp1252').decode('utf-8').encode('cp1252') ).

Я подозреваю, что ваши символы могут храниться как строки UTF8 в латинской (или подобной) базе данных. Вот почему у вас проблема с «двойным кодированием». Создание базы данных CHARSET UTF8 должно исправить ее. Может потребоваться также сброс / импорт данных, что-то вроде этого:

 $ mysqldump --default-character-set=latin1 --skip-set-charset --databases xxx > xxx.sql $ mysql --default-character-set=utf8 < xxx.sql 

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