【问题标题】:encoding issue special character csv to php编码问题特殊字符 csv 到 php
【发布时间】:2019-08-14 21:00:53
【问题描述】:

所以我有这个文件 (http://mountainmarathon.ch/components/com_chronoconnectivity6/chronoconnectivity/uploads/20190814194827_classifica-cat-standard-3.csv),它“应该”用 utf-8 编码。当我尝试通过 fgetcsv 或 file_get_contents 读取内容时,我得到了那些带有问号的黑色菱形,每个 ä,ö,ü 字符。

我已经知道这是一个编码问题,但据我所知,一切都是 / 应该是 utf-8 并且 utf-8 应该能够显示 ä,ö,ü,对吧?

我已经在这里检查了很多可能的解决方案,但没有找到任何解决方案。当我用记事本++打开文件时,钻石出现了同样奇怪的问题(即使我尝试更改编码 - 然后它变成了一个矩形)。 - 所以它的文件?

不,当我在我的 iphone(内部邮件应用程序)上打开 csv 文件时,特殊字符 ä,ö,ü 会正确显示。

到目前为止,我尝试的是来自不同堆栈溢出解决方案的不同 mb_convert_encoding 解决方案,但它们都不起作用。

我认为这个文件确实有些不正确,但为什么 iPhone 能够正确呈现内容?

有更多了解的人可以检查文件并告诉我如何通过 PHP 导入/使用其内容并摆脱那些编码问题吗?

标头通过以下方式设置为 UTF-8 header('Content-Type: text/html; charset=utf-8');

在终端“文件 -I 文件”中返回 UTF-8

我尝试了两台服务器(我的 mamp 使用 php7.3.1 和 webserver 使用 php7.x)

很抱歉,我不会发布过去三个小时以来我在此处和其他平台上检查过的每个问题的每个链接。是的,当然我已经在 php 手册(fgetcsv、mb_encode / check、utf8_encode / decode...等等)上检查了很多信息和 cmets,但没有找到解决我问题的方法。

最后,我针对这个函数检查了我的字符串(从文件获取内容):https://www.php.net/manual/de/function.mb-check-encoding.php#95289,它返回 FALSE。

现在没有任何意义了。

重现的代码很简单:

$content = file_get_contents($url);
var_dump($content);

我们如何才能将特殊字符显示为 ä,ö,ü 而不是带有问号的黑色菱形。

更新

根据您的分析,我检查了文件保存的具体情况。

首先:我通过电子邮件收到 csv,据我所知,它在 iso-8859-1 中

iOS 场景如下所示: 我在邮件应用程序中打开邮件并直接在邮件应用程序中显示 csv -> 一切正常。 接下来我通过邮件应用程序将文件导出到我的onedrive中->检查以在手机上打开文件->一切正常。 现在我可以通过文件 -I 检查我的 mac 上的字符集,它是 iso-8859-1

当我现在尝试使用这个文件和 php 的 utf8_encode 时 --> 一切都很好。

所以现在我必须了解之前出了什么问题,因为这是 MacOS 场景:

我打开(相同的)邮件并将相同的 src 文件保存到我的硬盘驱动器上,快速检查文件 - 我现在将 UTF-8 作为字符集。

在装有 Outlook 的 windows 机器上,保存文件,在记事本中打开字符被替换:ä=>d, ü=>|, ...

我现在认为 - 向我们发送此 csv 的人必须将文件导出为 utf-8,对我来说它看起来像它的 iso-8859-1,并且计算机在保存文件时会做一些奇怪的事情是这可能吗?

【问题讨论】:

  • 您发布的网址中的文件已损坏。

标签: php csv encoding


【解决方案1】:

此回复可能有点曲折,但希望它提供有用的信息。我正在终端窗口中的 ubuntu 工作站上运行这些命令。

我使用 Firefox 下载了文件。响应标头未指定任何字符集:

$ curl -sSL -D - http://mountainmarathon.ch/components/com_chronoconnectivity6/chronoconnectivity/uploads/20190814194827_classifica-cat-standard-3.csv -o /dev/null
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Wed, 14 Aug 2019 21:24:00 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Keep-Alive: timeout=60
Location: http://www.mountainmarathon.ch/components/com_chronoconnectivity6/chronoconnectivity/uploads/20190814194827_classifica-cat-standard-3.csv
Strict-Transport-Security: max-age=63072000

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 14 Aug 2019 21:24:00 GMT
Content-Type: text/csv
Content-Length: 39626
Connection: keep-alive
Keep-Alive: timeout=60
X-Content-Type-Options: nosniff
Last-Modified: Wed, 14 Aug 2019 19:48:27 GMT
ETag: "9aca-590190a7aa557"
Accept-Ranges: bytes
Strict-Transport-Security: max-age=63072000

如果我检查文件的开头,我确实看到了你所说的奇怪字符:

head -c 30 20190814194827_classifica-cat-standard-3.csv
11;1;102;Claudio;Br�ndli;198

第一个奇怪的字符用 3 个字节表示,ef bf bd

$ head -c 30 20190814194827_classifica-cat-standard-3.csv | xxd
00000000: 3131 3b31 3b31 3032 3b43 6c61 7564 696f  11;1;102;Claudio
00000010: 3b42 72ef bfbd 6e64 6c69 3b31 3938       ;Br...ndli;198

该字节序列对应于UTF-8 replacement character,即用于替换有问题的字节序列的字符。 这强烈表明原始文件本身没有您想要的带有变音符号的字符,而是包含替换字符。

我尝试在文本编辑器 (gedit) 和 LibreOffice calc 中使用多种不同的编码打开此文件,但字符在我尝试过的任何应用程序和编码组合中都无法正确显示。

我将这 3 个元音变音字符放在一个字符串中,但这些字符串都不匹配您文件中的 3 字节字符串:

$ echo "äöü" | xxd
00000000: c3a4 c3b6 c3bc 0a                        .......

为了澄清,我相信这些字符的 UTF-8 编码映射如下:

ä = c3a4
ö = c3b6
ü = c3bc

我可能错了,但我认为远程网站实际上可能包含 UTF-8 替换字符?我想知道咳出文件的 nginx 服务器是否可能试图解释该文件的内容并失败?我尝试设置一个 PHP 脚本来发送 accept-charset 标头,但它仍然会收到损坏的字符。

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.mountainmarathon.ch/components/com_chronoconnectivity6/chronoconnectivity/uploads/20190814194827_classifica-cat-standard-3.csv");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$headers = [
    'Accept-Charset: utf-8',
    'Accept-Encoding: gzip, deflate',
    'Accept-Language: en-US,en;q=0.5',
    'Cache-Control: no-cache',
//  'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0'
    'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 12_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Mobile/15E148 Safari/604.1'
Firefox/68.0'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$server_output = curl_exec ($ch);
file_put_contents("server-output.csv", $server_output);

curl_close ($ch);
echo "DONE\n";

总而言之,我认为您的原始源文件已经将您想要的字符(ä、ö、ü 等)替换为用于表示被误解的字节序列 (�) 的通用 UTF8 字符。是那个还是 CSV 文件被由于某种原因咳出来的服务器所破坏?你能告诉我更多关于在你的 iPhone 上查看这个文件的信息吗?你是用你的iphone从那个确切的网址请求它吗?

【讨论】:

  • 感谢您的分析 - 基于这些信息,我已经测试了一些东西并更新了我上面的问题,您认为会发生什么?
  • @Proximate 其他详细信息会有所帮助,但我不确定您的描述是否准确。听起来确实文件最初以 ISO-8859-1 的形式出现——这本身并没有什么问题——但是当你“打开(相同的)邮件并将相同的 src 文件保存到我的硬盘上”时,这似乎是该文件被损坏并认为它是utf8。您没有提供足够的详细信息来解决问题,但 CSV 数据可能会被邮件网关、邮件客户端或 FTP 客户端损坏。您不能直接从 OneDrive 检索文件吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-03
  • 1970-01-01
  • 2012-08-19
  • 2011-02-11
相关资源
最近更新 更多