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

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

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

поидее, браузер отправил http запрос, дальше смотрит в ответе
Content-Type: text/html; charset=windows-1251
и тело, в котором иногда есть
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
а дальше смотрит своим анализатором какая возможно кодировка в тексте.
Но что главнее для браузера всего, какой приоритет?
 
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. Кто кого?
 
alekciy спасибо за подробный ответ и статью.
Но если сайт проблемный и ты его не можешь нормально прочитать браузером, то зачем пытаться его прочитать скриптом?
<"При этом в самом скрипте используется одна кодировка, скрипт через HTTP заголовки явно задает её, но кодировка файла и то, что указывает скрипт не совпадают"
под скриптом ты подразумеваешь, как я понял, веб страницу, которую нужно прочитать. так в таком случае и твой скрипт не сможет норм прочитать страницу и браузер тоже.
Что-то я не понял разницы между тем, чтобы читать страницу скриптом или браузером, в чём разница-то в контексте кодировки.
 
Baranov_Dron
>Что-то я не понял разницы между тем, чтобы читать
>страницу скриптом или браузером, в чём разница-то в
>контексте кодировки.
В том, что если браузер на находит Meta тег в коде страницы, нет кодировки и в Content-Type HTTP заголовке, то пытается автоматом определить кодировку. Используется скорее всего что-то в духе тех алгоритмов, ссылки на которым ты сам здесь и привел.

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

К сожалению, встроеных функций в сам PHP для определению кодировки строки нет. Поэтому как ни крути встал вопрос либо написания такой функции самому, либо поиск котового решения. Но как это обычно и бывает, все изобрели уже до нас.
 
Хм если разложить по полочкам будет так:
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);
Я правильно всё понял?
ЗЫ блин ну и бажный же сайт, если в первом списке браузер выполняет пункт три, неужели таких много?!
 
Baranov_Dron
Да, все именно так.

Ну а насчет много или не много... статистику не собирал еще пока. Да и так ли это важно? Главное, что они есть. К тому же, даже не факт, что данные приходят в той кодировке, которая указана в http header. Сейчас обзавестить доменных именем и сайтом довольно просто. Но вот многие ли знаю, как правильно и корректно настраивать веб сервер? Думаю, таки меньшинство. Ибо даже среди тех, кто это делать обязан по служебной надобности, уровень квалификации не очень высокий.
 
<К тому же, даже не факт, что данные приходят в той кодировке, которая указана в http header
Ну тогда и в браузере будет выглядить текст закорючками, неужели админа не испугает, что постоянно нужно вручную менять кодировку в браузере и он не полезет в этот форум со словами помогите?
<Но вот многие ли знаю, как правильно и корректно настраивать веб сервер?
задача хостера вообще, вроде они выполняют её, конечно мало ли какой хостер попадётся...
Вообще интересный топик получился, много нового узнал!
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;
}
 
Сверху