PHP中的Unicode未知字符“�”检测

9

在PHP中有没有检测以下字符的方法?

我正在使用几种不同的算法修复一些UTF-8编码问题,需要能够检测字符串中是否存在。如何使用strpos实现?

仅将该字符粘贴到我的代码库中似乎不起作用。

if (strpos($names['decode'], '?') !== false || strpos($names['decode'], '�') !== false)

1
这种方法是错误的。你应该添加更多关于你正在做什么的信息,可能有更好的方法来实现你想要的目标。 - Pekka
1
最后一次尝试,使用0x00?请参见http://www.fileformat.info/info/unicode/char/0000/index.htm。 - Eric Fortis
Eric: 不是的。 Pekka: 一些麻烦的字符串被双重编码了,通过解码,当返回 ? 或 � 时,则该字符串未被双重编码。不确定如何检测。 - James
@James 我猜 0x00 这种方法行不通了? - Pekka
即使对某些人来说,使用==(宽松)比较字符'�'与0x00会成功,但不能用于检测字符'�',因为与0x00进行的==比较也会在与"""0"比较时通过。必须使用字符'�'与0x00的===(严格)比较,这很可能会失败。 - Adam
4个回答

19

使用iconv()函数将UTF-8字符串转换为UTF-8,使用//IGNORE参数会使得无效的UTF-8字符被丢弃。

因此,您可以通过比较iconv操作之前和之后的字符串长度来检测损坏的字符。如果它们不同,则包含损坏的字符。

测试用例(确保将文件保存为UTF-8):

<?php

header("Content-type: text/html; charset=utf-8");

$teststring = "Düsseldorf";

// Deliberately create broken string
// by encoding the original string as ISO-8859-1
$teststring_broken = utf8_decode($teststring); 

echo "Broken string: ".$teststring_broken ;

echo "<br>";

$teststring_converted = iconv("UTF-8", "UTF-8//IGNORE", $teststring_broken );

echo $teststring_converted;

echo "<br>";

if (strlen($teststring_converted) != strlen($teststring_broken  ))
 echo "The string contained an invalid character";

理论上,你可以去掉 //IGNORE 并且仅测试失败的(空)iconv 操作,但是 iconv 失败可能有其他原因,不仅仅是无效字符…我不知道。我会使用比较方法。


1
请注意,"//IGNORE"选项在最近版本的libiconv库上可能会失败,但是您可以使用以下解决方法:ini_set('mbstring.substitute_character', "none"); $teststring_converted = mb_convert_encoding($string, 'UTF-8', 'UTF-8'); - Adam

4

以下是我检测和纠正非UTF-8编码字符串的方法,以确保符合我的预期:

    $encoding = mb_detect_encoding($str, 'utf-8, iso-8859-1, ascii', true);
    if (strcasecmp($encoding, 'UTF-8') !== 0) {
      $str = iconv($encoding, 'utf-8', $str);
    }

1
据我所知,问号符号并不是单个字符。标准字体集中有许多不映射到符号的不同字符代码,并且这是所使用的默认符号。在PHP中进行检测,首先需要知道你使用的字体是什么。然后,您需要查看字体实现,看看哪些代码范围映射到“?”符号,然后查看给定字符是否在其中一个范围内。

1
实际上,这是一个特殊字符:它是U+FFFD,“Unicode 替换字符” - 当某个系统无法在该点解码数据(并替换为该字符)或者您没有字体时,它可能会出现。最好查看数据,看看您实际拥有哪些数据。 - Thanatos
我想我的意思是指不能正确解码的数据“范围”。 - Reinderien

0

我使用CUSTOM方法(使用str_replace)来清理未定义的字符:

    $input='a³';

    $text=str_replace("\n\n",  "sample000"        ,$text);
    $text=str_replace("\n",    "sample111"        ,$text);

    $text=filter_var($text,FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW);

    $text=str_replace("sample000",  "<br/><br/>"  ,$text);
    $text=str_replace("sample111",  "<br/>"       ,$text);

    echo $text; //outputs ------------>   a3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接