Я только начал заниматься php и боюсь, что мне нужна помощь, чтобы понять, как работать со строками utf-8.
Я работаю в Ubuntu 11.10 x86, php версии 5.3.6-13ubuntu3.2.У меня есть файл в кодировке utf-8 (vim :set encoding
подтверждает это), и я затем приступаю к его чтению с использованием
$file = fopen("file.txt", "r");
while(!feof($file)){
$line = fgets($file);
//...
}
fclose($file);
- с использованием
mb_detect_encoding($line)
отчетов UTF-8
- Если я сделаю
echo $line
, я смогу правильно увидеть строку (без искаженных символов) в браузере - , поэтому я думаю, что все в порядке с браузером и apache.Хотя я искал в своей конфигурации apache AddDefaultCharset и попытался добавить метатеги http для кодировки символов (на всякий случай)
Когда я пытаюсь разделитьстрока, использующая $arr = mb_split(';',$line)
поля полученного массива, содержат искаженные символы utf-8 (mb_detect_encoding($arr[0])
также сообщает utf-8).
Так что echo $arr[0]
приведет к чему-то вроде этого: ΑΘΗÎÎ
.
Я пробовал установить mb_detect_order('utf-8')
, mb_internal_encoding('utf-8')
, но ничего не изменилось.Я также попытался вручную определить utf-8, используя это регулярное выражение w3 perl , потому что я где-то читал, что mb_detect_encoding иногда может потерпеть неудачу (миф?), Но результаты были такими же.
Так что мойВопрос в том, как правильно разделить строку?Идет ли по пути mb_
неправильный путь?Чего мне не хватает?
Спасибо за вашу помощь!
ОБНОВЛЕНИЕ : я добавляю примеры строк и эквиваленты base64 (спасибо @chris 'за его предложение)
1. original string: "ΑΘΗΝΑ;ΑΙΓΑΛΕΩ;12242;37.99452;23.6889"
2. base64 encoded: "zpHOmM6Xzp3OkTvOkc6ZzpPOkc6bzpXOqTsxMjI0MjszNy45OTQ1MjsyMy42ODg5"
3. first part (the equivalent of "ΑΘΗΝΑ") base64 encoded before splitting: "zpHOmM6Xzp3OkQ=="
4. first part ($arr[0] after splitting): "ΑΘΗÎΑ"
5. first part after splitting base64 encoded: "77u/zpHOmM6Xzp3OkQ=="
Хорошо, так что после этого, кажется, есть разница 77u/
между 3. и 5. которая в соответствии с этим является меткой спецификации utf-8.Так как я могу избежать этого?
ОБНОВЛЕНИЕ 2 : Я проснулся освеженным сегодня и с вашими советами я попробовал это снова.Кажется, что $line=fgets($file)
правильно читает первую строку (без искаженных символов) и завершается с ошибкой для каждой последующей строки.Итак, я base64_encoded
первая и вторая строки, и 77u/
бомба появилась в строке base64'd только в первой строке .Затем я открыл файл с ошибками в vim и ввел :set nobomb
:w
, чтобы сохранить файл без BOM.Запуск php снова показал, что первая строка также была искажена.Основываясь на remove_utf8_bom
@ hakre, я добавил, что это дополнительная функция
function add_utf8_bom($str){
$bom= "\xEF\xBB\xBF";
return substr($str,0,3)===$bom?$str:$bom.$str;
}
и вуаля каждая строка теперь читается правильно.
Мне не очень нравится это решение,так как это кажется очень хакерским (я не могу поверить, что весь фреймворк / язык не обеспечивает способ иметь дело с нобомбированными строками).Так вы знаете альтернативный подход?В противном случае я продолжу описанное выше.
Спасибо @chris, @hakre и @jacob за уделенное время!
ОБНОВЛЕНИЕ 3 (решение) : получаетсяв конце концов, это была вещь браузера: недостаточно было добавить header('Content-type: text/html; charset=UTF-8')
и метатеги вроде <meta http-equiv="Content-type" value="text/html; charset=UTF-8" />
.Он также должен быть правильно заключен в секцию <html><body>
, иначе браузер не сможет правильно понять кодировку.Спасибо @jake за его предложение.
Мораль истории: прежде всего я должен узнать больше о html, прежде чем пытаться писать код для браузера.Спасибо всем за помощь и терпение.