У меня есть приложение, которое работает с клиентами со всего мира, и, естественно, я хочу, чтобы все, что входит в мои базы данных, было в кодировке UTF-8.
Основная проблема для меня заключается в том, что я не знаю, какой будет кодировка источника какой-либо строки - это может быть из текстового поля (использование <form accept-charset="utf-8">
полезно, только если пользователь фактически отправил форму), или это может быть из загруженного текстового файла, поэтому я действительно не могу контролировать ввод.
Что мне нужно, так это функция или класс, обеспечивающие, насколько это возможно, входящие в мою базу данных данные в кодировке UTF-8. Я пробовал, iconv(mb_detect_encoding($text), "UTF-8", $text);
но у него есть проблемы (если ввод 'fiancée', он возвращает 'fianc'). Я много чего перепробовал = /
Для загрузки файлов мне нравится идея попросить конечного пользователя указать кодировку, которую он использует, и показать им предварительный просмотр того, как будет выглядеть вывод, но это не помогает против злобных хакеров (на самом деле, это может сделать их жизнь немного проще).
Я читал другие вопросы SO по этому вопросу, но, похоже, все они имеют тонкие различия, такие как «Мне нужно проанализировать RSS-каналы» или «Я очищаю данные с веб-сайтов» (или, действительно, «Вы не можете»).
Но должно быть что-то, что, по крайней мере, стоит попробовать !
источник
UTF-8//IGNORE
в качестве второго параметра вiconv
?Ответы:
То, что вы просите, чрезвычайно сложно. Если возможно, лучше всего указать пользователю указать кодировку. Предотвращение атаки не должно быть намного проще или сложнее таким образом.
Тем не менее, вы можете попробовать сделать это:
Установка его в строгом может помочь вам получить лучший результат.
источник
mb_detect_encoding
исходный код в вашем php-дистрибутиве (где-то здесь: ext / mbstring / libmbfl / mbfl / mbfl_ident.c). Эта функция вообще не работает должным образом. Для некоторых кодировок у него даже есть «return true», лол. Другие находятся в функциях Ctrl + c Ctrl + v. Это потому, что вы не можете обнаружить кодирование без какого-либо словарного или статистического подхода (как у меня).mb_detect_encoding
просматривает список предоставленных кодировок и принимает первый, в котором нет недопустимых байтовых последовательностей в строке ... Для кодировок, в которых нет недопустимых байтовых последовательностей, таких как ISO-8859-1, это всегда верно , Никакой «умной» эвристики, и результаты сильно различаются в зависимости от списка (и порядка) кодировок, которые вы передаете.mb_detect_order()
хотя это значение по умолчанию для этого параметра, потому что он хотел установить для строгого обнаружения кодирования значение true (3-й параметр) :)На родине России у нас 4 популярных кодировки, поэтому ваш вопрос здесь очень востребован.
Только по кодам символов символов вы не можете обнаружить кодировку, потому что кодовые страницы пересекаются. Некоторые кодовые страницы на разных языках имеют даже полное пересечение. Итак, нам нужен другой подход .
Единственный способ работать с неизвестными кодировками - это работать с вероятностями. Итак, мы не хотим отвечать на вопрос «что такое кодировка этого текста?», Мы пытаемся понять, « какая кодировка этого текста наиболее вероятна? ».
Один парень из популярного российского технологического блога изобрел такой подход:
Создайте диапазон вероятности кодов символов в каждой кодировке, которую вы хотите поддерживать. Вы можете создать его, используя несколько больших текстов на вашем языке (например, художественную литературу, используйте Шекспира для английского и Толстого для русского, смеется). Вы получите что-то вроде этого:
Следующий. Вы берете текст в неизвестной кодировке и для каждой кодировки в своем «словаре вероятности» вы ищете частоту каждого символа в неизвестном кодированном тексте. Сумма вероятностей символов. Кодировка с большим рейтингом, вероятно, победитель. Лучшие результаты для больших текстов.
Если вам интересно , я с радостью помогу вам с этой задачей. Мы можем значительно повысить точность, создав список вероятностей из двух кодов.
Btw. mb_detect_encoding определенно не работает. Да вообще. Пожалуйста, посмотрите исходный код mb_detect_encoding в "ext / mbstring / libmbfl / mbfl / mbfl_ident.c".
источник
Вы, наверное, пытались это сделать, но почему бы просто не использовать функцию mb_convert_encoding? Он попытается автоматически определить набор символов из предоставленного текста или вы можете передать ему список.
Также я попытался запустить:
и результаты одинаковы для обоих. Как вы видите, что ваш текст урезан до 'fianc'? это в БД или в браузере?
источник
iconv
. Я пытался сделать почти чистый способ mb_ *. Что ты думаешь?Нет способа идентифицировать кодировку строки, которая является абсолютно точной. Есть способы попытаться угадать кодировку. Одним из таких способов, и, вероятно, в настоящее время является лучшим в PHP, является mb_detect_encoding (). Это будет сканировать вашу строку и искать вхождения вещи, уникальные для определенных кодировок. В зависимости от вашей строки, не может быть таких различимых случаев.
Возьмите кодировку ISO-8859-1 против ISO-8859-15 ( http://en.wikipedia.org/wiki/ISO/IEC_8859-15#Changes_from_ISO-8859-1 )
Есть только несколько разных символов, и, что еще хуже, они представлены одинаковыми байтами. Невозможно определить, получая строку, не зная ее кодировку, должен ли байт 0xA4 обозначать ¤ или € в вашей строке, поэтому нет способа узнать, какая именно кодировка.
(Примечание: вы можете добавить человеческий фактор или даже более продвинутую технику сканирования (например, то, что предлагает Oroboros102), чтобы попытаться выяснить, основываясь на окружающем контексте, если символ должен быть ¤ или €, хотя это выглядит как мост очень далеко)
Между UTF-8 и ISO-8859-1 есть более различимые различия, поэтому все же стоит попытаться выяснить это, когда вы не уверены, хотя вы можете и никогда не должны полагаться на то, что это правильно.
Интересно читать: http://kore-nordmann.de/blog/php_charset_encoding_FAQ.html#how-do-i-determine-the-charset-encoding-of-a-string
Есть и другие способы обеспечения правильной кодировки. Что касается форм, постарайтесь как можно чаще применять UTF-8 (посмотрите, что такое снеговик, чтобы убедиться, что отправка будет UTF-8 в каждом браузере: http://intertwingly.net/blog/2010/07/29/Rails-and -Snowmen ) После этого, по крайней мере, вы можете быть уверены, что каждый текст, отправленный через ваши формы, является utf_8. Что касается загруженных файлов, попробуйте запустить на нем команду unix 'file -i', например, через exec () (если это возможно на вашем сервере), чтобы помочь обнаружению (используя спецификацию документа). Что касается очистки данных, вы можете прочитать заголовки HTTP, это обычно указывает кодировку. При анализе файлов XML проверьте, содержат ли метаданные XML определение кодировки.
Вместо того, чтобы пытаться угадать кодировку автоматически, вы должны сначала попытаться убедиться в наличии определенной кодировки самостоятельно, или попытаться получить определение из источника, из которого вы его получили (если применимо), прежде чем прибегать к обнаружению.
источник
Здесь есть несколько действительно хороших ответов и попыток ответить на ваш вопрос. Я не мастер кодирования, но я понимаю ваше желание иметь чистый стек UTF-8 вплоть до вашей базы данных. Я использую
utf8mb4
кодировку MySQL для таблиц, полей и соединений.Моя ситуация сводилась к тому, что «я просто хочу, чтобы мои дезинфицирующие средства, валидаторы, бизнес-логика и подготовленные операторы имели дело с UTF-8, когда данные поступают из форм HTML или ссылок регистрации по электронной почте». Итак, по-простому, я начал с этой идеи:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
throw new RuntimeException
UTF-8
, продолжайте.Иначе, если это
ISO-8859-1
илиASCII
а. Попытка преобразования в UTF-8 (ожидание, не завершено)
б. Определить кодировку преобразованного значения
с. Если сообщаемое кодирование и преобразованное значение оба
UTF-8
, продолжаются.д. В противном случае,
throw new RuntimeException
Из моего абстрактного класса
Sanitizer
Можно привести аргумент, что я должен отделить проблемы кодирования от моего абстрактного
Sanitizer
класса и просто внедритьEncoder
объект в конкретный дочерний экземпляр классаSanitizer
. Однако главная проблема моего подхода заключается в том, что без дополнительных знаний я просто отвергаю ненужные типы кодирования (и полагаюсь на функции PHP mb_ *). Без дальнейшего изучения я не могу знать, вредит ли это некоторым группам населения или нет (или, если я теряю важную информацию). Итак, мне нужно узнать больше. Я нашел эту статью.Что абсолютно и положительно нужно знать каждому программисту о кодировках и наборах символов для работы с текстом
Кроме того, что происходит, когда зашифрованные данные добавляются в мои ссылки для регистрации по электронной почте (используя
OpenSSL
илиmcrypt
)? Может ли это помешать декодированию? А как насчет Windows-1252? А как насчет безопасности? Применениеutf8_decode()
иutf8_encode()
вSanitizer::isUTF8
сомнительно.Люди указали на недостатки в функциях PHP mb_ *. Я никогда не занимал время, чтобы исследовать
iconv
, но если это работает лучше, чем функции mb_ *, дайте мне знать.источник
Я не думаю, что это проблема. Приложение знает источник ввода. Если это из формы, используйте кодировку UTF-8 в вашем случае. Это работает. Просто убедитесь, что предоставленные данные правильно закодированы (проверка). Имейте в виду, что не все базы данных поддерживают UTF-8 в полном объеме.
Если это файл, вы не сохраните его в кодировке UTF-8 в базе данных, но в двоичном виде. Когда вы снова выводите файл, также используете двоичный вывод, тогда это полностью прозрачно.
Ваша идея хороша тем, что пользователь может сообщить кодировку, будь он / она может сказать в любом случае после загрузки файла, поскольку он является двоичным.
Поэтому я должен признать, что не вижу конкретной проблемы, которую вы поднимаете своим вопросом. Но, возможно, вы можете добавить более подробную информацию о вашей проблеме.
источник
Вы можете установить набор метрик, чтобы попытаться угадать, какая кодировка используется. Опять же, не идеально, но может поймать некоторые промахи из mb_detect_encoding ().
источник
mb_detect_encoding()
промахах, как вы думаете, мой ответ имеет шансы на снежный ком летом в Сахаре?Если вы готовы «взять это на консоль», я бы порекомендовал
enca
. В отличие от довольно упрощенногоmb_detect_encoding
, он использует «смесь синтаксического анализа, статистического анализа, угадывания и черной магии для определения их кодировок» (см. Справочную страницу ). Тем не менее, вам обычно приходится передавать язык входного файла, если вы хотите обнаружить такие кодировки для конкретной страны. (Однако, поmb_detect_encoding
существу, к нему предъявляются те же требования, поскольку кодировка должна отображаться «в нужном месте» в списке переданных кодировок, чтобы ее вообще можно было обнаружить.)enca
Также здесь можно найти : Как найти кодировку файла в Unix через скрипт (ы)источник
Кажется, что на ваш вопрос вполне ответили, но у меня есть подход, который может упростить ваш случай:
У меня была похожая проблема при попытке вернуть строковые данные из mysql, даже при настройке базы данных и php для возврата строк, отформатированных в utf-8. Единственный способ получить ошибку - это вернуть их из базы данных.
В конце концов, пробираясь через Интернет, я нашел очень простой способ справиться с этим:
Учитывая, что вы можете сохранять все эти типы строковых данных в MySQL в разных форматах и форматах, вам нужно лишь прямо в файле подключения php установить параметры сортировки в utf-8, например так:
Это означает, что сначала вы сохраняете данные в любом формате или сопоставлении и конвертируете их только при возврате в ваш файл php.
Надеюсь, это было полезно!
источник
Если текст получен из базы данных mysql, попробуйте добавить его после подключения BD.
mysqli_set_charset ($ con, "utf8");
https://www.php.net/manual/en/mysqli.set-charset.php
источник
параметры по умолчанию cURL:
Я попробовал что-то подобное. Это помогло мне. Если я найду информацию о метасимволах, я конвертирую, иначе ничего не делаю.
источник