Точное автоматическое определение кодировки. Либы есть?

phprus

Moderator
Команда форума
alekciy
Но учитывая опыт работы с предыдущими, закрадываются некоторые сомнения в эффективности.
Реализация на питоне это переписанный с С++ определитель кодировки из Mozilla.

По этому можно просто взять код на С++ и переписать его на php (или написать расширение к php), это будет гораздо проще.
 

Baranov_Dron

Новичок
Автор оригинала: alekciy
Поэтому для корректной обработки текста, полученного по ссылке, хочу однозначно знать кодировку ответа от сервера. Причем даже иметь возможность проверки корректности Content-Type заголовка, т.к. он в ответе сервера не всегда есть или не всегда его значение правильное
Content-Type: text/html; charset=UTF-8
Видел подобного рода строчки ответа сервера, строка понятна. Но интересно вот, что. Чем сервер(допустим апач) руководствуется для проставления этой строки?
 

Gas

может по одной?
Baranov_Dron
Обычно руководствуется программист, какую кодировку указать.
Вебсервер же mime-type ставит по расширению, а вот угадывание кодировки я б ему не доверил.
 

Baranov_Dron

Новичок
mime-type это text/html в данном случае? по расширению это понятно...
а вот кодировку, откуда он узнаёт, что посылать... и какая реакция у браузера?

поидее, браузер отправил http запрос, дальше смотрит в ответе
Content-Type: text/html; charset=windows-1251
и тело, в котором иногда есть
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
а дальше смотрит своим анализатором какая возможно кодировка в тексте.
Но что главнее для браузера всего, какой приоритет?
 

alekciy

Новичок
Baranov_Dron
>Чем сервер(допустим апач) руководствуется для
> проставления этой строки?
Для задания MIME type, как уже и сказал камрад Gas, он руководствуется расширением файла ( conf/mime.types ).
Для задания же кодировки он использует значение директивы AddDefaultCharset если MIME type запрашиваемого ресурса text/plain или text/html.

Существует модуль mod_charset_lite (со второй версии) который теоретически и должен заниматься такими вещами. Но:
1) он экспериментальный еще ( http://httpd.apache.org/docs/2.2/mod/mod_charset_lite.html ).
2) тестил на винде, работает не корректно.

Поэтому сейчас Апач отдает файл в той кодировке, в которой этот файл был сохранен. Т.е. Апач берет тупо поток байтов из файла и передает их как есть. Проблема определения кодировке лежит на браузере.

К слову сказать, с данной задачей все современные браузеры справляются вполне успешно. Поэтому при простом чтении файла браузером через веб сервер все нормально. Проблемы могут возникнуть в случае
когда файл читает скрипт (удаленный или локальный, мой случай как раз удаленный) и выводит его содержимое на странице.

При этом в самом скрипте используется одна кодировка, скрипт через HTTP заголовки явно задает её, но кодировка файла и то, что указывает скрипт не совпадают, а сам скрипт ни какого декодирования не делает. Получаем в теле страницы кусок текста кракозябрами . Если при этом внутри скрипта ведется какая либо обработака содержимого файла, а не просто вывод как есть, то искаженные данные уйдут на клиент и никаким переключением кодировок в браузере тексте прочесть не получиться. Данные будут искажены скриптом, текст из файла станет не читаемым.

Вроде изложил все доходчиво.

>Но что главнее для браузера всего, какой приоритет?
Не очевидные истины. Meta тег против HTTP header. Кто кого?
 

Baranov_Dron

Новичок
alekciy спасибо за подробный ответ и статью.
Но если сайт проблемный и ты его не можешь нормально прочитать браузером, то зачем пытаться его прочитать скриптом?
<"При этом в самом скрипте используется одна кодировка, скрипт через HTTP заголовки явно задает её, но кодировка файла и то, что указывает скрипт не совпадают"
под скриптом ты подразумеваешь, как я понял, веб страницу, которую нужно прочитать. так в таком случае и твой скрипт не сможет норм прочитать страницу и браузер тоже.
Что-то я не понял разницы между тем, чтобы читать страницу скриптом или браузером, в чём разница-то в контексте кодировки.
 

alekciy

Новичок
Baranov_Dron
>Что-то я не понял разницы между тем, чтобы читать
>страницу скриптом или браузером, в чём разница-то в
>контексте кодировки.
В том, что если браузер на находит Meta тег в коде страницы, нет кодировки и в Content-Type HTTP заголовке, то пытается автоматом определить кодировку. Используется скорее всего что-то в духе тех алгоритмов, ссылки на которым ты сам здесь и привел.

Другое дело скрипт. Он тупо получает поток байтов с удаленного сервера. Никакого автоматического перекодирования даже если будут заданы HTTP заголовки. Реализация приведения кодировок к нужному виду лежит полностью на авторе скрипта. Если он этим не озаботиться, то и на выходе скрипт выдает мусор. В том числе и поэтому возникла данная тема.

К сожалению, встроеных функций в сам PHP для определению кодировки строки нет. Поэтому как ни крути встал вопрос либо написания такой функции самому, либо поиск котового решения. Но как это обычно и бывает, все изобрели уже до нас.
 

Baranov_Dron

Новичок
Хм если разложить по полочкам будет так:
A) браузер:
1) смотрит http header - строчку типа
Content-Type: text/html; charset=UTF-8
eсли нашёл идёт в пункт 4
2) смотрит в теле документа строчку
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
ecли нашёл, то переход в пункт 4
3) пытается автоматом определить кодировку текста
4) отображает документ, в определённой кодировке
B) скрипт по идее должен так работать:
1) $charset = '';
2) пропарсить http header на наличие
Content-Type: text/html; charset=UTF-8
если нашёл, то записать в $charset найденную кодировку и идти в пункт 5
3) пропарсить тело на наличие
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
если нашёл, то записать в $charset найденную кодировку и идти в пункт 5
4) пытаться определить самому кодировку(с этим и была как понял проблема?)
5) $text = iconv($charset, nasha_kodirovko, $text);
Я правильно всё понял?
ЗЫ блин ну и бажный же сайт, если в первом списке браузер выполняет пункт три, неужели таких много?!
 

alekciy

Новичок
Baranov_Dron
Да, все именно так.

Ну а насчет много или не много... статистику не собирал еще пока. Да и так ли это важно? Главное, что они есть. К тому же, даже не факт, что данные приходят в той кодировке, которая указана в http header. Сейчас обзавестить доменных именем и сайтом довольно просто. Но вот многие ли знаю, как правильно и корректно настраивать веб сервер? Думаю, таки меньшинство. Ибо даже среди тех, кто это делать обязан по служебной надобности, уровень квалификации не очень высокий.
 

Baranov_Dron

Новичок
<К тому же, даже не факт, что данные приходят в той кодировке, которая указана в http header
Ну тогда и в браузере будет выглядить текст закорючками, неужели админа не испугает, что постоянно нужно вручную менять кодировку в браузере и он не полезет в этот форум со словами помогите?
<Но вот многие ли знаю, как правильно и корректно настраивать веб сервер?
задача хостера вообще, вроде они выполняют её, конечно мало ли какой хостер попадётся...
Вообще интересный топик получился, много нового узнал!
alekciy спасибо за этот топик!
 

alekciy

Новичок
Baranov_Dron
>задача хостера вообще, вроде они выполняют её
Не всегда. Да и как выполняет тоже вопрос. Но представим, что у нас идеальный хостер. Туже дефолтную кодировку, которая пойдет в HTTP заголовки может быть задана через директивы в .htaccess. А вот у моего хостера и вовсе можно задать в панели управления кодировку по умолчанию. Просто стоит переключатель и 3 кодировки на выбор. А через панель управления скорее всего и будет работать не очень искушенный пользователь. А детального описания зачем он и как работает нет.

Да что там говорить... Мне бывает нужно просматривать MSDN на сайте Microsoft-а. И не в первый раз уже попадаются страницы на которых часть данных идет кракозябрами, причем очень большая часть. А ведь там работают не глупые люди. Так чего же ждать от простых сайтавладельцев?

А тем более в наше время, когда преобрести простенький VDS сервер может любой человек, цены на них сейчас очень дешевые. А там root доступ, полная свобода. У меня таких две штуки, очень удобно. Ни каких ограничений на возможности кофнигурирования. Но это же так же означает, что и все серверы на нем нужно правильно сконфигурировать самому.
 
Для UTF8:

//# Функция обнаружения того, что строка $str закодирвана UTF-8 (бинарно)
//# Возвращает true если UTF-8 или false если ASCII
//# Алгоритм основан на анализе символов.
//# Можно вообще выключить распознавание, поставив просто return false;
function detect_utf($Str) {
for ($i=0; $i<strlen($Str); $i++) {
if (ord($Str[$i]) < 0x80) $n=0; # 0bbbbbbb
elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
elseif ((ord($Str[$i]) & 0xF0) == 0xF0) $n=3; # 1111bbbb
else return false; # Does not match any model
for ($j=0; $j<$n; $j++) { # n octets that match 10bbbbbb follow ?
if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80)) return false;
}
}
return true;
}
 
Сверху