我currentyl不知道如何对包含PHP中UTF-8编码字符串的数组进行排序.该阵列来自LDAP服务器,因此通过数据库排序(不会有问题)不是解决方案。 以下内容不适用于我的windows开发机器(尽管我认为这至少应该是一个可能的解决方案):
$array=array('Birnen', 'Äpfel', 'Ungetüme', 'Apfel', 'Ungetiere', 'Österreich');
$oldLocal=setlocale(LC_COLLATE, "0");
var_dump(setlocale(LC_COLLATE, 'German_Germany.65001'));
usort($array, 'strcoll');
var_dump(setlocale(LC_COLLATE, $oldLocal));
var_dump($array);
输出为:
string(20) "German_Germany.65001"
string(1) "C"
array(6) {
[0]=>
string(6) "Birnen"
[1]=>
string(9) "Ungetiere"
[2]=>
string(6) "Äpfel"
[3]=>
string(5) "Apfel"
[4]=>
string(9) "Ungetüme"
[5]=>
string(11) "Österreich"
}
这是完全废话.使用1252作为
setlocale()
的代码页
给出了另一个输出,但仍然是一个明显错误的输出:
string(19) "German_Germany.1252"
string(1) "C"
array(6) {
[0]=>
string(11) "Österreich"
[1]=>
string(6) "Äpfel"
[2]=>
string(5) "Apfel"
[3]=>
string(6) "Birnen"
[4]=>
string(9) "Ungetüme"
[5]=>
string(9) "Ungetiere"
}
有没有一种方法可以对具有UTF-8字符串语言环境的数组进行排序?
刚刚指出,这似乎是windows上的PHP问题,与
de_DE.utf8
相同
用作语言环境在Linux机器上工作.但是,针对此windows特定问题的解决方案会很好...
- 2021-1-121 #
- 2021-1-122 #
此问题的更新:
尽管有关此问题的讨论表明我们可以用
strcoll()
发现一个PHP错误 和/或setlocale()
,事实显然并非如此.问题是setlocale()
的windows CRT实现的局限性 (PHPssetlocale()
只是围绕CRT调用的薄包装).以下是对MSDN页面" setlocale,_wsetlocale"的引用:The set of available languages, country/region codes, and code pages includes all those supported by the Win32 NLS API except code pages that require more than two bytes per character, such as UTF-7 and UTF-8. If you provide a code page like UTF-7 or UTF-8, setlocale will fail, returning NULL. 语言集和 国家/地区代码支持 setlocale在"语言"和" 国家/地区字符串。
因此,当字符串是多字节编码时,不可能在windows上的PHP中使用可识别语言环境的字符串操作。
- 2021-1-123 #
最终,如果不使用重新编码的字符串(UTF),就无法以简单的方式解决此问题. -8→windows-1252或ISO-8859-1),这是由THP所建议的,因为Huppie发现了一个明显的PHP错误。 总结问题,我创建了以下代码片段,清楚地说明了问题是使用65001 windows-UTF-8代码页时的strcoll()函数。
function traceStrColl($a, $b) { $outValue=strcoll($a, $b); echo "$a $b $outValue\r\n"; return $outValue; } $locale=(defined('PHP_OS') && stristr(PHP_OS, 'win')) ? 'German_Germany.65001' : 'de_DE.utf8'; $string="ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜabcdefghijklmnopqrstuvwxyzäöüß"; $array=array(); for ($i=0; $i<mb_strlen($string, 'UTF-8'); $i++) { $array[]=mb_substr($string, $i, 1, 'UTF-8'); } $oldLocale=setlocale(LC_COLLATE, "0"); var_dump(setlocale(LC_COLLATE, $locale)); usort($array, 'traceStrColl'); setlocale(LC_COLLATE, $oldLocale); var_dump($array);
结果是:
string(20) "German_Germany.65001" a B 2147483647 [...] array(59) { [0]=> string(1) "c" [1]=> string(1) "B" [2]=> string(1) "s" [3]=> string(1) "C" [4]=> string(1) "k" [5]=> string(1) "D" [6]=> string(2) "ä" [7]=> string(1) "E" [8]=> string(1) "g" [...]
相同的代码片段可以在Linux机器上运行,而不会产生以下输出问题:
string(10) "de_DE.utf8" a B -1 [...] array(59) { [0]=> string(1) "a" [1]=> string(1) "A" [2]=> string(2) "ä" [3]=> string(2) "Ä" [4]=> string(1) "b" [5]=> string(1) "B" [6]=> string(1) "c" [7]=> string(1) "C" [...]
使用windows-1252(ISO-8859-1)编码的字符串时,该代码段也可以使用(当然,然后必须更改mb_ *编码和语言环境)。
我在bugs.php.net上提交了一个错误报告:错误#46165 strcoll()在windows上不适用于UTF-8字符串.如果您遇到相同的问题,可以在错误报告页面上向PHP团队提供反馈(另外两个可能相关的错误被归类为伪造-我认为这不是 错误是伪造;-)。
谢谢大家。
- 2021-1-124 #
这是一个非常复杂的问题,因为UTF-8编码的数据可以包含任何Unicode字符(即,来自许多8位编码的字符,它们在不同的语言环境中进行整理的方式不同) )。
也许如果您将UTF-8数据转换为Unicode(不熟悉PHP unicode函数,对不起),然后将其标准化为NFD或NFKD,然后对代码点进行排序,可能会提供一些对您有意义的排序规则(即 "Ä"之前的" A")。
检查我提供的链接。
编辑:由于您提到输入数据是清晰的(我假设它们都属于" windows-1252"代码页),因此您应该执行以下转换:UTF-8→Unicode→windows-1252, windows-1252编码的数据可以选择" CP1252"区域设置。
- 2021-1-125 #
在windows开发机上,使用代码页为1252的示例在这里工作得很好。
$array=array('Birnen', 'Äpfel', 'Ungetüme', 'Apfel', 'Ungetiere', 'Österreich'); $oldLocal=setlocale(LC_COLLATE, "0"); var_dump(setlocale(LC_COLLATE, 'German_Germany.1252')); usort($array, 'strcoll'); var_dump(setlocale(LC_COLLATE, $oldLocal)); var_dump($array);
... snip ...
这是PHP 5.2.6.顺便说一句
上面的例子是 wrong ,它使用ASCII编码而不是UTF-8.我确实跟踪了strcoll()调用并查看了发现的内容:function traceStrColl($a, $b) { $outValue = strcoll($a, $b); echo "$a $b $outValue\r\n"; return $outValue; } $array=array('Birnen', 'Äpfel', 'Ungetüme', 'Apfel', 'Ungetiere', 'Österreich'); setlocale(LC_COLLATE, 'German_Germany.65001'); usort($array, 'traceStrColl'); print_r($array);
给予:
UngetümeÄpfel2147483647 UngetümeBirnen 2147483647 UngetümeApfel 2147483647 UngetümeUngetiere 2147483647 ÖsterreichUngetüme2147483647 ÄpfelUngetiere 2147483647 ÄpfelBirnen 2147483647 ApfelÄpfel2147483647 Ungetiere Birnen 2147483647
我确实发现了一些错误报告,这些错误报告被标记为虚假... 您最好的选择是提交我认为的错误报告...
相关问题
- 用PHP和CURL发布多维数组phparrayspostcurl2021-01-11 22:58
- 在PHP和Javascript之间传输数组的最佳方法phpjavascriptajaxarraysdom2021-01-11 06:24
- php:嵌套数组第三层正在消失phparraysmultidimensionalarray2021-01-10 22:24
- php:使用数字键作为对象转换数组phparrayscasting2021-01-10 21:58
- arrays:意外的括号'['-PHPphparraysexplode2021-01-10 21:26
print:
Collator
类在PECL intl扩展中定义.它随PHP 5.3源一起分发,但对于某些版本可能已禁用.例如.在Debian中,它位于php5-intl软件包中。Collator::compare
对usort
有用 .