我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特定問题的解決方案会很好...
- 5月前1 #
- 5月前2 #
此問题的更新:
尽管有關此問题的讨論表明我们可以用
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中使用可識別語言環境的字元串操作。
- 5月前3 #
最终,如果不使用重新編碼的字元串(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团队提供反馈(另外两个可能相關的錯誤被归類為偽造-我认為這不是 錯誤是偽造;-)。
谢谢大家。
- 5月前4 #
這是一个非常複雜的問题,因為UTF-8編碼的資料可以包含任何Unicode字元(即,来自许多8位編碼的字元,它们在不同的語言環境中进行整理的方式不同) )。
也许如果您將UTF-8資料轉換為Unicode(不熟悉PHP unicode函式,對不起),然後將其標準化為NFD或NFKD,然後對代碼點进行排序,可能会提供一些對您有意義的排序規則(即 "Ä"之前的" A")。
檢查我提供的鏈接。
編輯:由於您提到輸入資料是清晰的(我假設它们都屬於" windows-1252"代碼頁),因此您應该執行以下轉換:UTF-8→Unicode→windows-1252, windows-1252編碼的資料可以選擇" CP1252"區域設置。
- 5月前5 #
在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
有用 .