Comments 82
Всем костылям костыль.
скорее баян — так шифровки дешифровывали еще при царе горохе.
но, это самый единственный идеологический правильный метод. еще правильнее только атака по словарю, но она намного более ресурсоемка.
но, это самый единственный идеологический правильный метод. еще правильнее только атака по словарю, но она намного более ресурсоемка.
Помню когда-то давно была проблема, что какой-то ИЕ отправлял данные на сервер, через ajax, в неверной кодировке. И так пробовал и этак, всё равно неверно, хоть убейся. Так вот, использовал костыль с добавлением параметра только для ИЕ и далее на php проверял. Если есть параметр, менял кодировку данных post. Самый костылистый костыль.
Проблема решалась формированием ответа запроса в виде полноценного xhtml с meta encoding. Сам в свое время столкнулся. ИЕ стал вести себя прилично, а остальные браузеры как работали ранее, так и работали дальше.
Не только ослик, но и сафари. Ибо utf8! Либо вы правильно работаете с кодировками (хедеры, меты и т.д.), либо используете утф. Это не проблема браузера, это с вами проблема.
Я бы рекомендовал использовать биграммы (триграммы) вместе с вероятностью их появления в тексте. Мне в одной из подобных проблем давал более точные результаты.
уверен, что N-граммы дадут более точный результат.
Похожий подход используется в одной из ссылок для детекта языков, но ИМХО для детекта кодировок это уже несколько избыточно.
Похожий подход используется в одной из ссылок для детекта языков, но ИМХО для детекта кодировок это уже несколько избыточно.
очевидно, что N-граммы дадут верный ответ с большей вероятностью, но калькуляция занимает больше времени, в то время как в случае биграмм имхо (естесственно не производил реальных замеров) в несколько раз повышается точность за счет небольшого увеличения времени исполнения.
в свое время тоже необходимо было решить такую задачу.
По-моему находил где-то решение с ngram на php
Однако, если уж автор залез внутрь php, не составит труда залезть внутрь firefox и выковырять оттуда модуль определения кодировок
По-моему находил где-то решение с ngram на php
Однако, если уж автор залез внутрь php, не составит труда залезть внутрь firefox и выковырять оттуда модуль определения кодировок
Решение с n-граммами на php есть по ссылке в топике (в разделе «поиск по хабру» вторая ссылка). Действительно на мой взгляд очень хорошее решение проблемы. Просто ИМХО несколько избыточно — для детекта языка в самый раз, а кодировки попроще можно детектить.
Исправьте по тексту «закасали рукава».
Модуль chardet — питоновский порт the auto-detection code in Mozilla и как это всё работает A composite approach to language/encoding detection.
я бы там посмотрел как реализовано
я бы там посмотрел как реализовано
Если сравнивать не частоты появления в тексте символов, а частоты пар, троек или большего количества символов идущих подряд, то определение будет гораздо точнее работать. Пар вполне достаточно. Где-то в сети и библиотеки такие быть должны.
habrahabr.ru/blogs/php/107945/#comment_3411483
тут об этом написано. Полностью согласен, но считаю полученную точность вполне удовлетворительной ).
тут об этом написано. Полностью согласен, но считаю полученную точность вполне удовлетворительной ).
Всё уже сказано до нас. Хоть и не начинай писать. :)
Хех, недолго осталось до наивного Байесовского классификатора.
интересная библиотека charset_x_win и метод определения кодировки ivr.webzone.ru/articles/defcod_2/index.htm
Кстати метод в данной библиотеки мне показался более интересным чем в статье.
Советую сбегать, почитать.
Советую сбегать, почитать.
Крутая штука, кстати. Жаль напрямую в юникод не умеет
function get_encoding($str){
$cp_list = array('utf-8', 'windows-1251');
foreach ($cp_list as $k=>$codepage){
if (md5($str) === md5(iconv($codepage, $codepage, $str))){
return $codepage;
}
}
return null;
}
сделайте substr() на строке в UTF-8, как иногда делают в тайтлах некоторых сайтов — и все, iconv() сразу споткнется с ворнингом.
чем она отличается, от функции с моего блога?
который здесь идёт как пример «убожества», которое работает 100%
который здесь идёт как пример «убожества», которое работает 100%
iconv() очень привередливый. Чуть только невалидный контент — и все.
Да и вообще — одному мне кажется, что делать через ошибки iconv() на неправильных кодировках нельзя?
Один только я думаю, что приложение на PHP обязано работать при error_reporting(E_ALL) без ошибок, ворнингов и нотисов, а на продакшене просто нужно его выключать на всякий случай?
Да и вообще — одному мне кажется, что делать через ошибки iconv() на неправильных кодировках нельзя?
Один только я думаю, что приложение на PHP обязано работать при error_reporting(E_ALL) без ошибок, ворнингов и нотисов, а на продакшене просто нужно его выключать на всякий случай?
я наверное что-то пропустил, но к чему этот ответ?
Это обоснование моего личного мнения насчет этой функции. И почему она не работает на 100%
а вы замеряли время работы своей функции по сравнению с иконв, и его ворнингом?
Пожалуйста, прочитайте обновление в посте про эту функцию.
Кроме того, что она генерирует ворнинги, она еще и не работает, поэтому измерять гипотетическую производительность смысла не вижу.
Кроме того, что она генерирует ворнинги, она еще и не работает, поэтому измерять гипотетическую производительность смысла не вижу.
Понимаете, была задача, определить текст в УТФ8 или в цп1251, функция работает 100%, без отказов.
Теперь скажите реальный пример определения огромного количества кодировок?
Теперь скажите реальный пример определения огромного количества кодировок?
Не совсем согласен. Функция фактически определяет, строка в utf8 или не в utf8. И работает 100% без отказов если на входе 100% валидная строка. То же самое намного проще сделает preg_match('#.#u'):
причем без ворнингов.
Задача в посте же ставилась — определять кодировку текста. Однобайтовых кириллических кодировок больше одной, поэтому и функция эта тут немного не в тему, мне кажется. Огромного количества кодировок не надо — достаточно почти всегда и двух однобайтовых кроме utf8 — cp1251 и koi8-r.
$str_utf8 = 'Русский текст';
$str_cp1251 = iconv('UTF-8', 'Windows-1251', $str_utf8);
var_dump(preg_match('#.#u', $str_utf8));
var_dump(preg_match('#.#u', $str_cp1251));
m00t@m00t:~/workspace/test$ php detect_encoding.php
int(1)
int(0)
причем без ворнингов.
Задача в посте же ставилась — определять кодировку текста. Однобайтовых кириллических кодировок больше одной, поэтому и функция эта тут немного не в тему, мне кажется. Огромного количества кодировок не надо — достаточно почти всегда и двух однобайтовых кроме utf8 — cp1251 и koi8-r.
тогда, задача сократилась к определению утф8, а всё остальное цп1251, да признаю.
за новый пример спасибо.
зы: на будущее не будь таким высокомерным, эта штука по жизни не очень помогает ;)
за новый пример спасибо.
зы: на будущее не будь таким высокомерным, эта штука по жизни не очень помогает ;)
К сожалению, не 100% результат
Большое вам спасибо, знай я этот метод раньше — мог бы сэкономить полдня бесплодных усилий:)
Да, вы правы, это оно, ссылку просмотрел, когда читал.
См обновление поста про эту функцию
Вот что люди только не придумают, чтобы на юникод не перейти
Хм, интересно, а как оно в enca реализовано…
Это намек кстати ;)
Да как раз хотел предложить с помощью Swig сгенерить php-модуль для enca и использовать его. Но вы же знаете PHP-шников :)
ну в крайнем случае через можно ведь и через шел запустить :)
Ага. А потом каждый раз при деплойменте сношаться с админами вражеских серверов, чтобы они установили/разрешили устанвливать свои расширения. Зачем усложнять и так достаточно простую задачу? 10-15 строк на PHP + несколько массивов данных из 15-30 элементов для каждой кодировки — и зачем генерировать php-модули, перегруженные функционалом для определения японских, корейских, китайских кодировок, которые большинству никогда и не понадобятся?
Скорей бы уже наступило светлое юникодное будущее)
это только подтверждает мнение о том, что пхп язык для дураков
раз даже стандартную билиотеку написали с такими вопиющими нарушениями
это просто смешно товарищи
раз даже стандартную билиотеку написали с такими вопиющими нарушениями
это просто смешно товарищи
а есть такое мнение оказывается?
таких приколов полно в библиотеках любых языков, начиная с библиотек языков, на которых эти языки и библиотеки для них были написаны.
вы же вряд ли в сорсу когда нибудь лазили?
таких приколов полно в библиотеках любых языков, начиная с библиотек языков, на которых эти языки и библиотеки для них были написаны.
вы же вряд ли в сорсу когда нибудь лазили?
По поводу статьи и кодировки выкинуть этот модуль надо mb_detect одинаково не работает
как для кирилических кодировок также и не работает для азиатских…
Было дело Китайскую и корейскую кодировку распозновал всегда как японскую =)
www.mozilla.org/projects/intl/UniversalCharsetDetection.html Это Теория на тему композитного распознования языков, по сути что автор сделал в статье подобный метод, частоты встречания символов.
как для кирилических кодировок также и не работает для азиатских…
Было дело Китайскую и корейскую кодировку распозновал всегда как японскую =)
www.mozilla.org/projects/intl/UniversalCharsetDetection.html Это Теория на тему композитного распознования языков, по сути что автор сделал в статье подобный метод, частоты встречания символов.
Частотное распределение имеет ошибку зависящую от количества символов и до 50 и даже до 100 она достаточно большая. Если надо распознавать фразу или даже несколько слов, то надо делать распределение или веса пары символов.
По большому счёту когда приходят данные в неизвестной кодировке важно определить — это UTF или нет, в противном случае принимаем волевое решение что это codepage 1251. На извращенцев, по недоразумению до сих пор использующих КОИ-как, EBCDIC или Mazowia можно забить имхо. А определить UTF не легко а очень легко: if (preg_match('//u', $string))…
В одном из проектов тоже столкнулся с проблемой определения кодировки приходящего текста.
В багтрекере PHP даже баг заведён по этому поводу: bugs.php.net/bug.php?id=38138
А для проверки кодировки текста я бы рекоммендовал использовать функцию mb_check_encoding(). Она работает достаточно адекватно. По крайней мере мои проверки (UTF-8, Windows-1251, KOI8-R, ISO-8859-5) не выявили проблем. В принципе на основе этой функции также можно написать небольшой велосипедик по определению самых распространённых кодировок.
Внутрь исходников расширения mbstring не заглядывал, но теперь стало интересно как работает вышеназванная mb_check_encoding. Вполне возможно там могут использоваться те же функции что и в md_detect_encoding, тогда на надёжность работы уже полагаться не придётся. Надо бы проверить.
В багтрекере PHP даже баг заведён по этому поводу: bugs.php.net/bug.php?id=38138
А для проверки кодировки текста я бы рекоммендовал использовать функцию mb_check_encoding(). Она работает достаточно адекватно. По крайней мере мои проверки (UTF-8, Windows-1251, KOI8-R, ISO-8859-5) не выявили проблем. В принципе на основе этой функции также можно написать небольшой велосипедик по определению самых распространённых кодировок.
Внутрь исходников расширения mbstring не заглядывал, но теперь стало интересно как работает вышеназванная mb_check_encoding. Вполне возможно там могут использоваться те же функции что и в md_detect_encoding, тогда на надёжность работы уже полагаться не придётся. Надо бы проверить.
Статистика, сэр))
Спасибо что проделали такой обьем работы!!! Тема — более чем актуальна!
Спасибо что проделали такой обьем работы!!! Тема — более чем актуальна!
Вы плохо искали ;)
forum.dklab.ru/viewtopic.php?t=37830
принцип работы — тот же:
forum.dklab.ru/viewtopic.php?t=37830
принцип работы — тот же:
function detect_encoding($string, $pattern_size = 50)
{
$list = array('cp1251', 'utf-8', 'ascii', '855', 'KOI8R', 'ISO-IR-111', 'CP866', 'KOI8U');
$c = strlen($string);
if ($c > $pattern_size)
{
$string = substr($string, floor(($c - $pattern_size) /2), $pattern_size);
$c = $pattern_size;
}
$reg1 = '/(\xE0|\xE5|\xE8|\xEE|\xF3|\xFB|\xFD|\xFE|\xFF)/i';
$reg2 = '/(\xE1|\xE2|\xE3|\xE4|\xE6|\xE7|\xE9|\xEA|\xEB|\xEC|\xED|\xEF|\xF0|\xF1|\xF2|\xF4|\xF5|\xF6|\xF7|\xF8|\xF9|\xFA|\xFC)/i';
$mk = 10000;
$enc = 'ascii';
foreach ($list as $item)
{
$sample1 = @iconv($item, 'cp1251', $string);
$gl = @preg_match_all($reg1, $sample1, $arr);
$sl = @preg_match_all($reg2, $sample1, $arr);
if (!$gl || !$sl) continue;
$k = abs(3 - ($sl / $gl));
$k += $c - $gl - $sl;
if ($k < $mk)
{
$enc = $item;
$mk = $k;
}
}
return $enc;
Если у нас из вариантов только cp1251 и utf-8, то можно просто посчитать все русские буквы
https://gist.github.com/luchaninov/a8469ce649c8428cd02be793165f260a
https://gist.github.com/luchaninov/a8469ce649c8428cd02be793165f260a
Sign up to leave a comment.
Определение кодировки текста в PHP — обзор существующих решений плюс еще один велосипед