【问题标题】:Non-UTF8 files (Google CSV file)非 UTF8 文件(Google CSV 文件)
【发布时间】:2011-01-27 00:01:21
【问题描述】:

我在处理上传的文件时遇到了奇怪的编码问题。

我需要接受任何类型的文本文件,并且能够阅读其中的内容。尤其是从 Google 通讯录导出下载的文件时遇到问题。

我已经完成了通常的 utf8_encode/decode、mb_detect_encoding 等。总是像字符串是 UTF-8 一样返回,并尝试了许多 iconv 选项来尝试恢复编码,但没有成功。

test.php

header('Content-type: text/html; charset=UTF-8');

if ($stream = fopen($_FILES['list']['tmp_name'], 'r'))
{
    $string = stream_get_contents($stream);

    fclose($stream);
}

echo substr($string, 0, 50);
var_dump(substr($string, 0, 50));
echo base64_encode(serialize(substr($string, 0, 50)));

输出

��N�a�m�e�,�G�i�v�e�n� �N�a�m�e�,�A�d�d�i�t�i�o�n�
��N�a�m�e�,�G�i�v�e�n� �N�a�m�e�,�A�d�d�i�t�i�o�n�
czo1MDoi//5OAGEAbQBlACwARwBpAHYAZQBuACAATgBhAG0AZQAsAEEAZABkAGkAdABpAG8AbgAiOw==

【问题讨论】:

  • 编码错误太模糊。我们需要一个例子。尝试在此处发布base64_encode(serialize($excerpt))
  • 更新了示例摘录。
  • $string 从何而来?你能展示你用来获取它的代码吗?你用什么编码输出这个?
  • 更新了 stream_get_contents。注意:我尝试了几种处理上传文件的方法,结果相同。如果我将上传的文本文件的内容复制到我的计算机上,然后上传一个具有相同内容的新文本文件,就可以了。我假设文件本身的文件编码是非 UTF-8 开头的。

标签: php utf-8 character-encoding


【解决方案1】:

字符串的开头带有字节 \xFF \xFE 代表 UTF-16 Little Endian 的 Byte Order Mark。所有字母实际上都是两字节序列。主要是前导 \0,后跟 ASCII 字符。

在控制台上打印它们将使终端客户端正确解释 UTF-16 序列。但是您需要手动解码(最好通过 iconv)以使整个数组可显示。

【讨论】:

  • codeunit.co.za/2010/03/05/… 提供了转换代码,感谢您注意 BOM
  • @James,你在大型导入场景中使用过这个 fn() 吗?我面临着用户上传大文件(10-200mb)进行导入的情况,在每个字段上运行它似乎并不可行,而且我没有奢侈地将它们全部加载到内存中。
  • @Jakub:您可以为此使用iconv("UTF-16","UTF-8",$str) 函数。或者,如果上传的文件不应该被读入,请尝试system("recode UTF-16..UTF-8 '$filename'"); 在 BSD/Linux 服务器上进行快速就地转换。
【解决方案2】:

当我解码 base64 片段时,我看到了一个奇怪的混合字符串:s:50:"\xff\xfeN\x00a\x00m\x00e\x00,\x00G\x00i\x00v\x00e\x00n\x00 \x00N\x00a\x00m\x00e\x00,\x00A\x00d\x00d\x00i\x00t\x00i\x00o\x00n\x00"。第二个: 之后的部分是包含在ASCII " 中的2 字节Unicode (UCS2) 字符串,而“s”和“50”是纯ASCII。 \ff\fe 片段是 UCS2 字符串的字节顺序标记。这很疯狂,但可以解析。

我假设您将输入字符串拆分为:,从开头和结尾剥离",并尝试分别解码每个结果字符串。

【讨论】:

    猜你喜欢
    • 2019-05-18
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2015-07-04
    相关资源
    最近更新 更多