Беда с UTF-8 символами; то, что я вижу, не то, что я храню

Я попытался использовать UTF-8 и столкнулся с проблемой.

Я перепробовал так много вещей; Вот результаты, которые я получил:

???? вместо азиатских символов. Даже для европейского текста я получилSe?or заSeñor.Странная тарабарщина (моджибаке), такая какSeñor или же新浪新闻 за新浪新闻.Черные бриллианты, такие как Se or.Наконец, я попал в ситуацию, когда данные были потеряны или, по крайней мере, обрезаны:Se заSeñor.Даже когда я получил текстсмотреть верно, это неСортировать правильно.

Что я делаю неправильно? Как я могу исправитькод? Могу ли я восстановитьданныеесли да, то как?

Ответы на вопрос(3)

Установите для своего языка IDE код UTF8

Добавьте в заголовок вашей веб-страницы, где вы собираете данные формы.

Проверьте, что определение таблицы MySQL выглядит следующим образом:

CREATE TABLE your_table (
  ...
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Если вы используете PDO, убедитесь, что

$options = array(PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES utf8'); 
$dbL = new PDO($pdo, $user, $pass, $options);

Если у вас уже есть большая база данных с вышеуказанной проблемой, вы можете попробовать экспортировать SIDU с правильной кодировкой и импортировать обратно с UTF8. Удачи

 Rick James14 июл. 2016 г., 05:06
PDO лучше сделать с опцией charset:$db = new PDO('dblib:host=host;dbname=db;charset=UTF8', $user, $pwd);  (Это указано в ссылке на мой документ «charcoll».)
 Rick James14 июл. 2016 г., 05:03
(Ответ на свой вопрос - это особенность этого форума.) Я работал в течение многих лет, пытаясь сделать ответ кратким, но полным.
 Rick James14 июл. 2016 г., 05:23
Я рекомендую любую шестнадцатеричную строку или строку с действительно фиксированной длиной, в большинстве случаев, должна быть ascii. Это необходимо для переопределения «нового» значения по умолчанию для utf8, которое занимает в 3 раза больше места дляCHAR(n), (Это укусило некоторых людей, которые не заметили, что общесистемное значение по умолчанию изменилось на utf8.)
 Rick James14 июл. 2016 г., 05:04
DEFAULT CHARSET для таблицы это просто по умолчанию. Это может и иногда должно быть переопределено в определении столбца.
 SIDU14 июл. 2016 г., 05:09
Вы на 20К более опытны, чем я :) Да, вы можете установить кодировку для столбца. Старайтесь не злоупотреблять этим. В конечном итоге больше времени на управление. Точно так же вы можете предоставить доступ к определенному столбцу таблицы MySQL. Однако вы не должны использовать его, если у вас нет лучшей альтернативы.
 Rick James10 мая 2018 г., 06:00
@ppmakeitcount - Нет необходимости перезагружать базу данных. Тем не менее, обязательно используйте соответствующиеALTER, как обсуждено здесь:mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases
 spencer759309 нояб. 2017 г., 17:01
@ppmakeitcount: нет,ALTER DATABASE заявление не требует перезапуска MySQL, чтобы вступить в силу. Однако изменение набора символов по умолчанию для базы данныхне повлиять на любые таблицы в настоящее время в базе данных; это влияет только на новые таблицы, напримерCREATE TABLE которые не определяют набор символов по умолчанию для таблицы; это когда набор символов по умолчанию базы данных вступает в игру. (Аналогичным образом, изменение набора символов по умолчанию для таблицы не влияет на столбцы, уже находящиеся в таблице; это влияет только на столбцы, добавленные в таблицу, если не указан набор символов для столбцов.
 ppmakeitcount08 окт. 2017 г., 04:16
Если я изменю базу данных на utf8, следует ли перезапустить базу данных, чтобы изменения вступили в силу? И есть ли шансы на потерю данных.

как настроен сервер, вы должны соответственно изменить кодировку. utf8 из того, что вы сказали, должен работать лучше, однако, если вы получаете странные символы, это может помочь, если вы измените веб-страницу Encode на Ansi. Это помогло мне, когда я настраивал PHP MYSQLI, это может помочь вам понять большеhttps://superuser.com/questions/762473/ansi-to-utf-8-in-notepad

 Rick James03 авг. 2016 г., 18:27
БлокнотеANSI вероятно, ближе всего к MySQLlatin1, 0x93 в этой ссылке и, вероятно, пришел из какого-то места, как Word. Вы можете конвертировать в utf8 (hexE2809C) или скажите MySQL, что данныеlatin1 и надеюсь, что вы не споткнетесь в другом месте.
Решение Вопроса

Вы перечислили пять основных случаевCHARACTER SET неприятности.

Лучшая практика

В дальнейшем лучше всего использоватьCHARACTER SET utf8mb4 а такжеCOLLATION utf8mb4_unicode_520_ci, (Существует более новая версия сопоставления Unicode в конвейере.)

utf8mb4 это надмножествоutf8 тем, что он обрабатывает 4-байтовые коды utf8, которые нужны Emoji и некоторым китайцам.

За пределами MySQL «UTF-8» относится ко всем кодировкам размеров, следовательно, фактически таким же, как MySQLutf8mb4неutf8.

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

Обзор того, что выдолжен делать

Настройте ваш редактор и т. Д. На UTF-8.HTML-формы должны начинаться как<form accept-charset="UTF-8">.Ваши байты закодированы как UTF-8.Установите UTF-8 в качестве кодировки, используемой в клиенте.Объявите столбец / таблицуCHARACTER SET utf8mb4 (Проверить сSHOW CREATE TABLE.)<meta charset=UTF-8> в начале HTML

UTF-8 на всем пути

Подробнее о компьютерных языках (и следующие его разделы)

Проверьте данные

Просмотр данных с помощью инструмента или сSELECT нельзя доверять. Слишком много таких клиентов, особенно браузеров, пытаются компенсировать неправильные кодировки и показывают правильный текст, даже если база данных искажена. Итак, выберите таблицу и столбец с неанглийским текстом и выполните

SELECT col, HEX(col) FROM tbl WHERE ...

HEX для правильно сохраненного UTF-8 будет

Для пробела (на любом языке):20Для английского:4x, 5x, 6x, или же7xДля большей части Западной Европы буквы с акцентом должны бытьCxyyКириллица, иврит и фарси / арабский:DxyyБольшая часть Азии:ExyyzzЭмодзи и некоторые из китайцев:F0yyzzwwПодробнее

Конкретные причины и исправления замеченных проблем

усеченный текст (Se заSeñor):

Сохраняемые байты не кодируются как utf8mb4. Почини это.Кроме того, проверьте, что соединение во время чтения является UTF-8.

Черные бриллианты с вопросительными знаками (Se�or заSeñor); существует один из этих случаев:

Случай 1 (оригинальные байты былине UTF-8):

Сохраняемые байты не кодируются как utf8. Почини это.Соединение (илиSET NAMES) дляINSERT а также SELECT не было utf8 / utf8mb4. Почини это.Также проверьте, что столбец в базе данныхCHARACTER SET utf8 (или utf8mb4).

Случай 2 (оригинальные байтымы UTF-8):

Соединение (илиSET NAMES) дляSELECT не было utf8 / utf8mb4. Почини это.Также проверьте, что столбец в базе данныхCHARACTER SET utf8 (или utf8mb4).

Черные бриллианты появляются только когда браузер настроен на<meta charset=UTF-8>.

Вопросительные знаки (обычные, а не черные бриллианты) (Se?or заSeñor):

Сохраняемые байты не кодируются как utf8 / utf8mb4. Почини это.Столбец в базе данных неCHARACTER SET utf8 (или utf8mb4). Почини это. (ИспользованиеSHOW CREATE TABLE.)Кроме того, проверьте, что соединение во время чтения является UTF-8.

кракозябры (Señor заSeñor): (Это обсуждение также относится кДвойное кодирование, что не обязательно видно.)

Сохраняемые байты должны быть в кодировке UTF-8. Почини это.Соединение когдаINSERTing а такжеSELECTing текст должен указывать utf8 или utf8mb4. Почини это.Столбец должен быть объявленCHARACTER SET utf8 (или utf8mb4). Почини это.HTML должен начинаться с<meta charset=UTF-8>.

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

Двойное кодирование можно подтвердить, выполнивSELECT .. HEX .. описано выше.

é should come back C3A9, but instead shows C383C2A9
The Emoji  should come back F09F91BD, but comes back C3B0C5B8E28098C2BD

То есть гекс примерно вдвое длиннее, чем должен быть. Это вызвано преобразованием из latin1 (или что-то еще) в utf8, затем обработкой этих байтов, как будто они были latin1 и повторением преобразования. Сортировка (и сравнение) не работает правильно, потому что это, например, сортировка, как если бы строка былаSeñor.

Исправление данных, где это возможно

Засокращение а такжеВопросительные знаки, данные потеряны.

Закракозябры / Двойное кодирование...

ЗаЧерные бриллианты...

(Я должен продолжить это в другом вопросе / ответе.)

 Rick James06 окт. 2016 г., 03:19
 david_adler15 янв. 2018 г., 17:50
Если клиент, база данных и таблицы находятся вutf8mb4 Кажется, я могу хранить смайлики в порядке. Некоторые блоги предлагают также настройкиcollation-server а такжеcharacter-set-server в mysqld. Мне действительно нужно изменитьmysqld Какое значение имеет настройка сервера?
 Rick James29 июн. 2018 г., 19:06
Советы по настройкепитон, PHP, и о40 других языков
 Rick James10 мая 2018 г., 05:56
С MySQL 8.0 (сейчас выпущен) по умолчаниюutf8mb4 а такжеutf8mb4_0900_ai_ci, Большинству пользователей следует использовать их без учета других кодировок и сопоставлений.
 Rick James03 янв. 2019 г., 23:35
Еще одно примечание: еслиFUNCTION или жеSTORED PROCEDURE Возможно, вы не использовали нужный набор символов при его создании.DROP Это,SET NAMES; зановоCREATE Это.
 Rick James15 янв. 2018 г., 19:47
@david_adler - Есть несколько способов получить эффект от этих настроек. Лучше всего использовать параметры подключения клиентов. Второй лучший по выполнениюSET NAMES utf8mb4 сразу после подключения. В конце концов, это объявление кодировки вклиент.

Ваш ответ на вопрос