【发布时间】:2010-04-16 10:33:23
【问题描述】:
PHP 的 str_replace() 仅用于 ANSI 字符串,因此可以破坏 UTF-8 字符串。但是,考虑到它是二进制安全的,如果只给它有效的 UTF-8 字符串作为参数,它会正常工作吗?
编辑:我不是在寻找替代函数,我只是想知道这个假设是否正确。
【问题讨论】:
PHP 的 str_replace() 仅用于 ANSI 字符串,因此可以破坏 UTF-8 字符串。但是,考虑到它是二进制安全的,如果只给它有效的 UTF-8 字符串作为参数,它会正常工作吗?
编辑:我不是在寻找替代函数,我只是想知道这个假设是否正确。
【问题讨论】:
是的。 UTF-8 特意设计为允许这种和其他类似的非 Unicode 感知处理。
在 UTF-8 中,任何表示有效字符的非 ASCII 字节序列始终以 \xC0-\xFF 范围内的字节开头。该字节可能不会出现在序列中的任何其他位置,因此您无法创建与字符的一部分匹配的有效 UTF-8 序列。
旧的多字节编码不是这种情况,字节序列的不同部分是无法区分的。这导致了很多问题,例如尝试替换 Shift-JIS 字符串中的 ASCII 反斜杠(其中字节 \x5C 可能是表示其他内容的字符序列的第二个字节)。
【讨论】:
这是正确的,因为 UTF-8 多字节字符完全是非 ASCII(128+ 字节值)字符,以一个定义后面有多少字节的字节开头,因此您不会意外地匹配一个 UTF-8 的一部分多字节字符与另一个。
可视化(抽象地):
a 用于 ASCII 字符2x 用于 2 字节字符3xx 用于 3 字节字符4xxx 用于 4 字节字符如果你匹配,比如说,a2x3xx(a ASCII 范围内的字节),因为a x,并且2x 不能是3xx 或4xxx 的子集,等等,你可以确保你的 UTF-8 正确匹配,前提是所有字符串都是绝对有效的 UTF-8。
编辑:请参阅bobince 的答案以获得不那么抽象的解释。
【讨论】:
嗯,我确实有一个反例:我有一个 UTF8 编码设置“.ini”文件,指定应用程序设置,如电子邮件发件人名称。它说的是:
email_from = Märta
我从那里读到变量$sender。现在我替换了消息正文(又是 UTF8)
问候 {发件人}
$message = str_replace("{sender}",$sender_name,$message);
电子邮件在各个方面都绝对正确,但发件人完全崩溃了。当 UTF 字符串出现问题时,还有其他情况(例如 explode() )。它在转换之前是健康的,但在转换之后却不是。很抱歉,似乎无法纠正这种行为。
编辑:实际上,explode() 参与了 .ini 文件的解析,所以问题很可能出在那个函数上,所以 str_replace() 很可能是无辜的。
【讨论】:
str_replace 完全谋杀 UTF8 字符串,我不知道有任何解决方法。
不,你不能。
从实践中我告诉你,如果你有一些像◊等的多字节符号,而其他的不是多字节,它就不能正常工作,因为有些符号需要 2-4 来放置它们,
str_replace 采用固定字节,并替换......结果我们得到的东西不是任何符号垃圾等。
【讨论】:
是的,我认为这是正确的,至少我找不到任何反例。
【讨论】: