当前位置: 首页 > 知识库问答 >
问题:

如何在PHP(浏览器)中再现表示非UTF8字符串

黄靖
2023-03-14

我通过导入收到了一个未知字符编码的字符串。如何在浏览器中显示这样的字符串,以便将其复制为PHP代码?

我想用一个例子来说明这个问题。

$stringUTF8 = "The price is 15 €";
$stringWin1252 = mb_convert_encoding($stringUTF8,'CP1252');

var_dump($stringWin1252);    //string(17) "The price is 15 �"
var_export($stringWin1252);  // 'The price is 15 �'

与var_导出一起交付的字符串与原始字符串不匹配。所有无法识别的字符都将替换为� 象征该字符串仅在此处使用mb_convert_编码生成,用于测试目的。这里的字符编码是已知的。实际上,它来自导入,例如,带有文件内容()的导入,字符编码未知。

我所期望的具有改进的var_导出的输出如下所示:

"The price is 15 \x80"

我的解决方法是找到所有非UTF8字符,然后用十六进制显示它们。这里显示的代码过于广泛。

另一个变体是以十六进制PHP符号输出所有字符。

function strToHex2($str) {
    return '\x'.rtrim(chunk_split(strtoupper(bin2hex($str)),2,'\x'),'\x');
}
echo strToHex2($stringWin1252);

输出:

\x54\x68\x65\x20\x70\x72\x69\x63\x65\x20\x69\x73\x20\x31\x35\x20\x80

这个变体非常适合纯二进制数据,但对于一般文本来说相当大且难以阅读。

换句话说,我的问题是:

如何将所有非UTF8字符从字符串更改为PHP十六进制表示“\xnn”,并保留正确的UTF8字符。

共有1个答案

姚伟
2023-03-14

我将从问题本身开始:

如何在PHP(浏览器)中再现表示非UTF8字符串

答案很简单,只需在HTML标记或HTTP头中发送正确的编码。

但那不是你真正的问题。事实上,我不是100%确定真正的问题是什么,但我会试着遵循你写的。

我通过导入收到一个未知字符编码的字符串。

这才是我们真正需要开始的地方。如果您有一个未知字符串,那么您实际上只有二进制数据。如果您无法确定这些字节代表什么,我也不希望浏览器或其他任何人能够理解它。但是,如果您可以确定这些字节代表什么,那么再次向客户机发送正确的编码。

如何在浏览器中显示这样的字符串,以便将其复制为PHP代码?

你在这里往返,这是在问问题。唯一安全可靠的答案是Unicode,它带有一种官方支持的编码,如UTF-8、UTF-16等。

var_export传递的字符串与原始字符串不匹配。所有无法识别的字符都被符号替换。

作为示例输入的字符串没有以x80的字节序列结尾。相反,您输入的字符在Unicode中是20AC,并在UTF-8中表示为三个字节xE2 x82 xAC。函数mb_convert_encoding没有每个编码中所有逻辑字符的映射,因此对于这种特定情况,它不知道如何将“欧元符号”映射到CP1252代码页。每当字符转换失败时,将使用UnicodeFFFD字符来代替。

该字符串仅在此处使用mb_convert_编码生成,用于测试目的。

即使这只是为了测试目的,它仍然会弄乱数据,理解前一段很重要。

这里的字符编码是已知的。实际上,它来自导入,例如带有file\u get\u contents(),字符编码未知。

在这一点上,我们又回到了任意字节。您可以使用PHP猜测,或者如果您有已知数据的语料库,您可以构建一些启发式。

我期望的具有改进var_export的输出如下:"价格为15\x80"

var_dumpvar_export都是为了确切地向您展示变量内部的内容,更改它们会带来巨大的BC问题。(实际上有一个RFC用于创建一个新的转储函数,但我认为它并没有达到您想要的效果。)

在PHP中,字符串只是字节数组,因此调用这些函数会将这些字节数组转储到流中,您的浏览器或控制台或其他任何程序会采用当前编码,并尝试将这些字节与当前字体匹配。如果您的字体不支持,将显示其中一个替换字符。(或者,有时设备试图猜测这些字节代表什么,这就是为什么您会看到或类似内容。)再说一遍,您的浏览器/控制台可以做到这一点,而PHP并没有做到这一点。

我的解决方案是查找所有非UTF8字符

那可能不是你想要的。首先,它假设字符是UTF-8,您说过这不是您可以做出的假设。第二,如果一个文件的字节序列不是有效的UTF-8,那么可能是一个坏文件

如何将所有非UTF8字符从字符串更改为PHP十六进制表示“\xnn”,并保留正确的UTF8字符。

真正的解决方案是在应用程序中始终使用Unicode,并在存储/输出内容时强制执行编码。这也意味着,在查看这些数据时,您拥有能够显示这些代码点的字体。

当你摄取数据时,你需要先让它达到这个理智的点,这并不总是容易的。然而,一旦你是Unicode,你应该(大部分)是安全的。(对于“大部分”,我在看你表情符号!)

但你如何转化?这是最难的部分。此答案显示如何手动将CP1252转换为UTF-8。基本上,对您想要支持的每个代码点重复。

如果你不想这样做,而且你真的想得到转义序列,那么我想我应该逐字节检查字符串,然后任何超过x7F的内容都会被转义:

$s = "The price is 15 \x80";
$buf = '';
foreach(str_split($s) as $c){
    $buf .= $c >= "\x80" ? '\x' . bin2hex($c) : $c;
}

var_dump($buf);

// string(20) "The price is 15 \x80"
 类似资料:
  • 问题内容: 在我的雪花数据库中,一个表具有非utf8字符。我如何在它上面创建仅包含utf8字符的视图;通过排除非utf8字符的行还是替换它们?谢谢 问题答案: 应该可以使用以下测试来检查非utf: 但是那时我没有数据可以测试。 要将字符串重新编码为utf-8,可以使用JavaScript函数:

  • 问题内容: 我在从字符串中删除非utf8字符时出现问题,这些字符无法正确显示。像这样的字符0x97 0x61 0x6C 0x6F(十六进制表示) 删除它们的最佳方法是什么?正则表达式还是其他? 问题答案: 使用正则表达式方法: 它搜索UTF-8序列,并将其捕获到组1中。它还与无法标识为UTF-8序列的一部分的单个字节匹配,但不捕获这些字节。替换是捕获到组1中的任何内容。这将有效删除所有无效字节。

  • 问题内容: 我有一些来自json文件的文本。在本文中,我应用了UTF8编码,但是该编码器无法识别非标准字符,并且为大写字符,是否有一种方法可以净化我的字符串? 我的功能: 问题答案: 我找到了解决方案。 UTF8采用8位表ASCII表,而UTF16采用16位ASCII表,解决方案很简单,只需将函数修改为:

  • 我正面临一个奇怪的问题。我已经把所有东西都放在php.ini文件里了。但是我不能在浏览器中显示任何错误。我google设置了. ini文件,并做了所有需要的事情。但是我仍然不能在浏览器中显示错误信息。我的PHP ini设置, 我尝试使用以下代码查看错误消息, 实际上文件示例不可用。所以它必须显示致命错误。但它显示的是空白页。 你能告诉我怎么解决这个问题吗?我不知道我错过了什么。

  • 问题内容: 在我的servlet中,我使用下面的代码在浏览器中打开PDF文件,但是,它显示了一个下载对话框。 我做错了什么? 问题答案: 你可以尝试用

  • 问题内容: 我们在CMS上有一个ckeditor。我们的最终用户将通过该ckeditor输入一些长文章。我们需要一种方法来防止这些文章的连字符出现换行。 无论如何,是否可以防止所有浏览器上的连字符断行? 还是ckeditor可以选择防止这种情况? 问题答案: 恐怕没有比将文本分割成“单词”(由空格分隔的非空白字符序列)并包装每个在标记内包含连字符的“单词”更可靠的方法了。因此,输入数据将变为。 您