在PHP中解析UTF-8字符串char-by-char

时间:2014-11-16 00:16:29

标签: php string encoding utf-8

对不起,如果我问明显的话,但我似乎无法为简单的任务找到合适的解决方案。在输入上,我有一个由用户提供的字符串,用UTF-8编码编码。我需要删除除0x20(或标签符号)之外的所有低于0x7(或空格)的字符进行清理。

以下适用于ANSI字符串,但不适用于UTF-8:

$newName = "";
$ln = strlen($name);
for($i = 0; $i < $ln; $i++)
{
    $ch = substr($name, $i, 1);
    $och = ord($ch);
    if($och >= 0x20 ||
        $och == 0x9)
    {
        $newName .= $ch;
    }
}

它完全错过了UTF-8编码的字符并将它们视为字节。我一直在寻找人们建议使用mb_功能的帖子,但这对我没有帮助。 (例如,我尝试调用mb_strlen($name, "utf-8");而不是strlen,但它仍然返回BYTEs中字符串的长度而不是字符。)

知道如何在PHP中执行此操作吗?

PS。对不起,我的PHP有些生疏。

2 个答案:

答案 0 :(得分:1)

如果您使用多字节功能(mb_),则必须将它们用于所有内容。在此示例中,您应使用mb_strlen()mb_substr()

它无法正常工作的原因可能是因为您使用的是ord()。它仅适用于ASCII值:

ord
(PHP 4, PHP 5)
ord — Return ASCII value of character
...
Returns the ASCII value of the first character of string.

换句话说,如果你将一个多字节字符扔进ord(),它只会使用第一个字节,然后扔掉其余的字符。

答案 1 :(得分:0)

哇,PHP是一种混乱的语言。这对我有用(但是对于更长的一段文本来说会运行多慢......):

function normalizeName($name, $encoding_2_use, $encoding_used)
{
    //'$name' = string to normalize
    //          INFO: Must be encoded with '$encoding_used' encoding
    //'$encoding_2_use' = encoding to use for return string (example: "utf-8")
    //'$encoding_used' = encoding used to encode '$name' (can be also "utf-8")
    //RETURN:
    //      = Name normalized, or
    //      = "" if error
    $resName = "";

    $ln = mb_strlen($name, $encoding_used);
    if($ln !== false)
    {
        for($i = 0; $i < $ln; $i++)
        {
            $ch = mb_substr($name, $i, 1, $encoding_used);

            $arp = unpack('N', mb_convert_encoding($ch, 'UCS-4BE', $encoding_used));
            if(count($arp) >= 1)
            {
                $och = intval($arp[1]);    //Index 1?! I don't understand why, but it works...
                if($och >= 0x20 || $och == 0x9)
                {
                    $ch2 = mb_convert_encoding('&#'.$och.';', $encoding_2_use, 'HTML-ENTITIES');
                    $resName .= $ch2;
                }
            }
        }
    }

    return $resName;
}