Проблема кодировки символов - вывод PHP, читаемый .NET, через HttpWebRequest - PullRequest
2 голосов
/ 15 декабря 2008

У меня есть скрипт PHP (работающий на сервере Linux), который выводит имена некоторых файлов на сервере. Эти имена файлов выводятся в простом текстовом формате.

Этот вывод считывается из программы VB.NET с использованием HttpWebRequest, HttpWebResponse и StreamReader.

Проблема в том, что некоторые имена выводимых файлов содержат ... необычные символы. В частности, символ «раздел» (§).

Если я просматриваю вывод сценария PHP в веб-браузере, символ отображается нормально.

Но когда я читаю вывод PHP-скрипта в мою .NET-программу, символ не отображается правильно (он выглядит как универсальный символ «блок»).

Я перепробовал все варианты кодировки символов, которые можно использовать при чтении потока ответов (из HttpWebResponse). Я попытался вывести поток непосредственно в текстовый файл (не очень хорошо), отобразив его в TextBox (не очень хорошо), и даже при просмотре результатов непосредственно в отладчике Visual Studio символ отображается как блок, а не как символ "раздел".

Я изучил вывод в шестнадцатеричном редакторе (как было предложено в связанном вопросе: « как вы устраняете проблемы кодировки символов .» *

Когда я выписываю символ раздела (§) из самого .NET, шестнадцатеричные байты, которые я вижу, представляющие его, представляют собой «c2 a7» (имеет смысл, если это Unicode, верно? Требуется два байта?). Когда я записываю вывод из сценария PHP непосредственно в файл и проверяю его с помощью шестнадцатеричного редактора, символ отображается как «ef bf bd» - три байта вместо двух?

Я в растерянности относительно того, что делать - если мне нужно указать какую-то другую кодировку символов, или я упускаю что-то очевидное по этому поводу.

Вот код, который используется для получения выходных данных скрипта PHP (комментарии в стиле VB изменены, чтобы они правильно отображались на этом сайте):


Dim myRequest As HttpWebRequest = WebRequest.Create("http://www.example.com/sample.php")

Dim myResponse As HttpWebResponse = myRequest.GetResponse()

// read the response stream
Dim myReader As New StreamReader(myResponse.GetResponseStream())

// read the entire output in one block (just as an example)
Dim theOutput as String = myReader.ReadToEnd()

Есть идеи?

  • Я использую неправильный вид StreamReader? (Я попытался передать кодировку символов в вызове для создания нового StreamReader - я попробовал все те, которые находятся в System.Text.Encoding - UTF-8, UTF-7, ASCII, UTF-32, Unicode, и др.)
  • Должен ли я использовать другой метод для чтения выходных данных сценария PHP?
  • Что-то, что я должен делать по-другому на стороне PHP при выводе текста?

ОБНОВЛЕННАЯ ИНФОРМАЦИЯ:

  • Вывод из PHP специально кодируется UTF-8 путем вызова: utf8_encode($file);
  • Когда я выписал символ из .NET, я скопировал и вставил символ из приложения Character Map в Windows. Я также скопировал и вставил его непосредственно из имени файла (в Windows) и с самой этой веб-страницы - все выдали одинаковое шестнадцатеричное значение при записи (c2 a7).
  • Да, "символ раздела", о котором я говорю, это U + 00A7 (ALT + 0167 в Windows, в соответствии с картой символов).
  • Тип содержимого задается явно через header('Content-Type: text/html; charset=utf-8'); в самом начале PHP-скрипта.

UPDATE:

Сам понял, но я не смог бы сделать это без помощи людей, которые ответили. Спасибо!

Ответы [ 4 ]

2 голосов
/ 15 декабря 2008

понял это !!

Как и многие другие вещи, все просто в ретроспективе!

Джон Скит был прав - это было означало , чтобы быть UTF-8, но определенно не было.

Оказывается, в исходном сценарии, который я использовал (до того, как я сократил его, чтобы упростить отладку), был некоторый дополнительный вывод текста скриптом, который не был включен в вызов utf8_encode(). Это привело к выводу всей страницы в формате ISO-8859-1 вместо UTF-8.

Я заметил это, когда проверил свойство «кодирования» моего сценария тестирования (в Firefox «Просмотр информации о странице»). Это был UTF-8 для сценария тестирования, но ISO-8859-1. Производственный сценарий также напечатал дату файла; это не было включено в вызов utf8_encode - и это привело к тому, что весь вывод изменился на ISO-08859-1.

[Вставьте звук, когда я хлопаю здесь по лбу]

Спасибо всем, кто ответил! Вы были очень полезны!

1 голос
/ 15 декабря 2008

Вы используете utf8_encode($file), хорошо, но PHP также возвращает тип контента как UTF-8? Можете ли вы проверить заголовок Content-Type, возвращаемый вашей страницей PHP? Вам следует обратить особое внимание на поле charset, чтобы убедиться, что у вас есть что-то вроде этого:

Content-Type: text/html; charset=utf-8

Я вижу, как браузер может правильно отображать символ, когда .NET (по праву или по ошибке) не работает. Браузеры обычно стараются быть как можно более сильными и прощающими. Браузер, который вы используете, может определять фактическую кодировку символов из последовательностей символов.

1 голос
/ 15 декабря 2008

PHP дает вам контроль над кодировкой вообще? Обычно не стоит догадываться об этом.

Когда вы говорите, что вы написали символ из .NET, какую кодировку вы использовали? Какой фактический код Unicode это? В Unicode U + 00A7 есть символ раздела - это то, что вы имеете в виду? Я понятия не имею, почему PHP будет представлять это как "ef bf bd".

Использование StreamReader должно быть хорошо, но вам нужно знать правильную кодировку.

РЕДАКТИРОВАТЬ: Хорошо, значит означало , чтобы быть UTF-8, и, конечно, нет - поэтому проблема на стороне PHP. Если вы запустите utf8_encode($file), а затем явно распечатаете байты результата (не мешая веб-серверу), что произойдет? Я действительно удивлен, что браузеру удается получить правильный символ, хотя ... это просто обычный HTML? Вы уверены, что все "ef bf bd" это просто символ раздела?

Является ли этот веб-сервер общедоступным? Если бы я мог направить свой браузер на это, я мог бы быть в состоянии понять, что происходит.

0 голосов
/ 06 февраля 2012

Используя приведенный выше совет, я создал простое решение, которое заключается в создании файла со следующим:

$feed = header("Content-Type: text/html; charset=utf-8");
$feed.=utf8_encode(readfile(rawurldecode($_GET["url"])));
$feed = fread(rawurldecode($_GET["url"]));
die($feed);

Это PHP, но его легко перенести на любой другой язык. Затем вы просто вызываете любой URL-адрес, который хотите использовать, который вызывает проблемы с UTF8 (я обнаружил проблему с RSS-фидом, поэтому мне это нужно), а URL-адрес проблемного файла в URL-адресе получает переменную, например http://example.com/fix-my-rss.php?url=http://anotherexample.com/broken.rss

Это загрузит файл и вернет его вам как другой файл, без проблем, который вы можете загрузить во что-то еще, например, в программу чтения с экрана. Вы можете аналогичным образом изменить его, чтобы прочитать строку или любой другой код, в котором у вас есть код ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...