字符编码问题 - PHP输出,由.NET读取,通过HttpWebRequest

时间:2008-12-15 16:02:52

标签: .net php vb.net encoding character-encoding

我有一个PHP脚本(在Linux服务器上运行),它输出服务器上某些文件的名称。它以简单的纯文本格式输出这些文件名。

使用HttpWebRequest,HttpWebResponse和StreamReader从VB.NET程序读取此输出。

问题是输出的某些文件名包含......不常见的字符。具体来说,“部分”符号(§)。

如果我在Web浏览器中查看PHP脚本的输出,则符号显示正常。

但是当我将PHP脚本的输出读入我的.NET程序时,该符号没有正确显示(它显示为通用的“块”符号)。

我已经尝试了在读取响应流时可以使用的所有不同的字符编码选项(来自HttpWebResponse)。我已经尝试将流直接输出到文本文件(不好),在TextBox中显示它(不好),甚至直接在Visual Studio调试器中查看结果时,字符显示为块而不是“部分”符号。

我已经在十六进制编辑器中检查了输出(正如相关问题“how do you troubleshoot character encoding problems”所示。

当我从.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的输出通过调用:utf8_encode($file);
  • 专门编码为UTF-8
  • 当我从.NET中写出符号时,我从Windows中的Character Map应用程序复制并粘贴了符号。我也复制了&直接从文件的名称(在Windows中)和从此网页本身粘贴它 - 在写出时都给出了相同的十六进制值(c2 a7)。
  • 是的,我正在谈论的“部分符号”是U + 00A7(Windows上的ALT + 0167,根据字符映射)。
  • 内容类型通过PHP脚本开头的header('Content-Type: text/html; charset=utf-8');显式设置。

更新

自己想出来,但如果没有得到回答的人的帮助,我就无法做到。谢谢!

4 个答案:

答案 0 :(得分:2)

弄清楚!!

像很多东西一样,回想起来很简单!

Jon Skeet是正确的 - 意味着是UTF-8,但绝对不是。

事实证明,在我使用的原始脚本中(在我将其剥离以使其更易于调试之前),脚本中还有一些其他文本输出未包含在utf8_encode()调用中。这导致整个页面以ISO-8859-1而不是UTF-8输出。

当我检查测试脚本的“编码”属性时(在Firefox中,“查看页面信息”),我注意到了这一点。测试脚本是UTF-8,但ISO-8859-1。生产脚本还打印了文件的日期;这并没有包含在对utf8_encode的调用中 - 这导致整个输出更改为ISO-08859-1。

[插入我的额头拍打我的额头]

感谢所有回答的人!你非常乐于助人!

答案 1 :(得分:1)

PHP能让你控制编码吗?只是猜测它通常不是一个好主意。

当你说你已经从.NET写出符号时,你使用了什么编码?它是什么实际的Unicode代码点? unicode U+00A7处有一个部分符号 - 是你的意思吗?我不知道为什么PHP会将其表示为“ef bf bd”。

使用StreamReader应该没问题,但您需要知道正确的编码。

编辑:好的,所以意味着是UTF-8,当然不是 - 所以问题出在PHP方面。如果你运行utf8_encode($file)然后显式打印结果的字节(没有Web服务器妨碍)会发生什么?我真的很惊讶浏览器正在设法获得正确的符号......这只是简单的HTML吗?你确定所有“ef bf bd”只是部分符号吗?

此网络服务器是否在任何地方公开?如果我可以将浏览器指向它,我可能能够解决正在发生的事情。

答案 2 :(得分:1)

您正在使用utf8_encode($file),很好,但是PHP也将内容类型返回为UTF-8吗?你能检查PHP页面返回的Content-Type标题吗?你应该特别注意charset字段,以确保你有这样的东西:

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

我可以看到浏览器在.NET(正确或错误地)失败时如何正确显示角色。浏览器通常尽量保持健壮和宽容。您正在使用的浏览器可能会从字符序列中推断出实际的字符编码。

答案 3 :(得分:0)

使用上面的建议我创建了一个简单的解决方案,即创建一个包含以下内容的文件:

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

这是PHP,但可以轻松移植到任何其他语言。然后你只需调用你想要使用的任何导致UTF8问题的URL(我发现RSS源存在问题,因此我需要它),URL中的问题文件的URL获取变量,如http://example.com/fix-my-rss.php?url=http://anotherexample.com/broken.rss < / p>

然后,这将加载到文件中,并将其作为另一个文件返回给您,而不会出现问题,您可以将其加载到其他内容中,例如屏幕阅读器。您可以类似地修改它以读取字符串或其他任何有问题代码的地方。