【问题标题】:PHP string functions: which ones will work with UTF-8?PHP 字符串函数:哪些适用于 UTF-8?
【发布时间】:2017-11-15 04:56:03
【问题描述】:

PHP documentation 中列出了在字节级别上工作的字符串函数。这适用于 SBCS 字符串,但不适用于 MBCS 字符串。幸运的是,一种著名的 UTF-8 编码向后兼容最高 7 位 US-ASCII。

自 PHP 5.6 起,默认编码已更改为 UTF-8,但它的字符串函数没有。众所周知的替代方案是iconvMultibyte StringIntl。如果以正确的方式编译,PCRE 函数也可以兼容 MBCS。

当需要将 SBCS 年龄代码转换为符合 VMBCS (UTF-8) 标准时,需要重写标准 PHP 字节字符串函数以保证 MBCS 安全。虽然最基本的函数(如strpos())有一个mb_* 变体(如mb_strpos()),但大多数PHP 的字符串函数没有mb_ 对应物。为了继续使用,它们必须被重写。

在第一阶段,需要确定哪些 SBCS 字符串函数可以工作,尽管它们是面向字节的。有些已经在 SO 上被识别出来,我现在正在寻找的是一个完整的函数列表,这些函数可以与 UTF-8 一起使用,或者在谨慎使用时,例如仅使用 US-ASCII 的参数。澄清一下,问题不在于chr()crc32() 之类的字节字符串函数,而在于获取如下函数列表:

  • 不安全:count_chars() 计算字节数,...
  • 注意:只要参数是 US-ASCII,ltrim() 就可以工作,...
  • 安全:str_repeat() 可用于 MBCS 字符串,...

有人知道这样的清单吗?

【问题讨论】:

  • 你在文档中搜索过the list of PHP string functions吗?
  • 是的,我只需要一个列表就可以知道要重写哪些函数。
  • 提供一个东西列表不适合 SO,但它在 PHP 中的问题已经足够了,这是一个合理的问题。不幸的是,最可行的事情是真正了解 UTF-8 以及每个单独的字符串函数的作用,从中您可以判断自己所做的事情是否安全。是的,我知道这不是一个非常令人满意的答案……
  • @deceze 我已经看到很多关于函数 X 是否是多字节安全的问题。虽然这些问题确实合适,但我同意不合适的说法。我考虑过 SO 文档,但我读过他们将改变结构。

标签: php string multibyte-functions


【解决方案1】:

核心 PHP SBCS 字符串函数

假设default encoding of PHP is set to UTF-8这些字符串函数将起作用

很遗憾,所有其他字符串函数都不能使用 UTF-8。 障碍:

  • 大小写处理或空格不适用于 UTF-8
  • 参数和返回值中的字符串长度不是字符长度
  • 字符串处理导致数据损坏
  • 字符串函数完全面向ASCII

在某些情况下,当参数是 US-ASCII 和 长度是字节长度。

二进制字符串函数还是有用的

  • bin2hex将二进制数据转换为十六进制表示
  • chr 返回特定字符(=字节)
  • convert_uudecode解码一个uuencoded字符串
  • convert_uuencodeUuencode 一个字符串
  • crc32计算字符串的crc32多项式
  • crypt单向字符串哈希
  • hex2bin 解码十六进制编码的二进制字符串
  • md5_file 计算给定文件的 md5 哈希
  • md5计算一个字符串的md5哈希
  • ord返回字符的ASCII值(=字节)
  • sha1_file计算文件的sha1哈希
  • sha1计算字符串的sha1哈希

配置函数不适用

Regular expression functions 不考虑编码和转码功能。

扩展

在很多情况下,Multibyte String 提供 UTF-8 变体:

  • mb_convert_case 对字符串进行大小写折叠
  • mb_parse_str解析GET/POST/COOKIE数据并设置全局变量
  • mb_split 使用正则表达式拆分多字节字符串
  • mb_strcut获取部分字符串
  • mb_strimwidth获取指定宽度的截断字符串
  • mb_stripos 查找一个字符串在另一个字符串中第一次出现的位置,不区分大小写
  • mb_stristr 在另一个字符串中查找第一次出现的字符串,不区分大小写
  • mb_strlen获取字符串长度
  • mb_strpos 查找字符串在字符串中第一次出现的位置
  • mb_strrchr 查找一个字符在另一个字符串中的最后一次出现
  • mb_strrichr 在另一个字符串中查找最后一次出现的字符,不区分大小写
  • mb_strripos 在另一个字符串中查找最后一次出现的位置,不区分大小写
  • mb_strrpos在字符串中查找字符串最后出现的位置
  • mb_strstr 在另一个字符串中查找第一次出现的字符串
  • mb_strtolower 将字符串设为小写
  • mb_strtoupper 将字符串设为大写
  • mb_strwidth返回字符串宽度
  • mb_substr_count统计子串出现的次数
  • mb_substr获取部分字符串

iconv 提供了最少的字符串函数:

最后,Intl 作为i18n 的一部分,具有许多额外且强大的 Unicode 功能(但没有正则表达式)。某些功能与其他字符串函数重叠。关于字符串函数,这些是:

【讨论】:

    【解决方案2】:

    PHP standard string functions 无法正确处理多字节字符串。它们将参数作为单字节字符串处理,无论您传递给它们的是什么类型的字符串。它们不是对字符进行操作,而是对字节进行操作。

    PHP 不保留每个字符串的编码。它以相同的方式处理所有这些。

    mbstring PHP extension 提供的PHP multi-byte string functions 可以处理多种字符编码,在编码之间进行转换并自动检测给定字符串的编码。它们对字符进行操作,并且能够处理固定长度编码(UTF-16,f.e.)和可变长度编码(UTF-8)。

    【讨论】:

    • +1 基本正确,PHP 在字节级别上运行,是的,这意味着这些函数会弄乱您的 MBCS。但是 UTF-8 是 US-ASCII 兼容的,尽管它们是 8 位字节设计的,但某些功能仍然可以工作。
    • 所有 PHP 字符串函数都适用于 UTF-8 编码的字符串,只要字符串仅使用 7 位 ASCII 字符(因为前 128 个字符的编码在 ASCII 和 UTF-8 中是相同的) .
    • 有很多标准的字符串函数可以很好地处理 UTF-8 字符串,例如str_replace。由于他们正在做的事情的性质,无论他们是以字节还是字符为基础操作都没有关系。另一方面,其他人将失败,例如trim 带有自定义的非 ASCII 字符掩码(但使用纯 ASCII 掩码也可以正常工作)。
    • @axiac 不正确,检查htmlentities 哪个does work with UTF-8
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-09
    相关资源
    最近更新 更多