Ist die Prüfung für UTF-8 strings in PHP eine zuverlässige Methode?
Ich gefunden habe, eine nützliche Funktion auf eine andere Antwort und ich Frage mich, wenn jemand könnte mir erklären, was es macht und ob es zuverlässig ist. Ich war mit mb_detect_encoding(), aber es war falsch, beim Lesen von einem ISO 8859-1-Datei auf einem Linux-OS.
Diese Funktion scheint zu funktionieren, in allen Fällen, die ich getestet.
Hier ist die Frage: Get file encoding
Hier ist die Funktion:
function isUTF8($string){
return preg_match('%(?:
[\xC2-\xDF][\x80-\xBF] # Non-overlong 2-byte
|\xE0[\xA0-\xBF][\x80-\xBF] # Excluding overlongs
|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # Straight 3-byte
|\xED[\x80-\x9F][\x80-\xBF] # Excluding surrogates
|\xF0[\x90-\xBF][\x80-\xBF]{2} # Planes 1-3
|[\xF1-\xF3][\x80-\xBF]{3} # Planes 4-15
|\xF4[\x80-\x8F][\x80-\xBF]{2} # Plane 16
)+%xs', $string);
}
Ist dies eine sichere Möglichkeit, die Erkennung von UTF-8 strings?
Was genau macht es? Es kann robuster gemacht werden?
- Warum nicht so etwas wie
mb_detect_encoding
(php.net/manual/en/function.mb-detect-encoding.php)? - Möchte nur erwähnen, dass diese Funktion denkt, dass "1" ein string ist nicht utf8, während es ist (zu sein klar, es ist nur ein ascii -, aber es ist immer noch aufgenommen werden sollte utf8)
- haben Sie Lesen die Frage überhaupt?
- Habe gelesen, dass die Frage, aber ich erinnere mich nicht, zu sehen, dass Sie wurden mit
mb_detect_encoding
früher; sorry about that. Ich denke immer noch, es lohnt sich mitmb_detect_encoding
hier, obwohl... selbst wenn es eingehüllt in etwas anderes. Überprüfen Sie heraus diesen Kommentar von Greg Theiß als auch, wenn Sie die chance haben, über die Verwendung des "strict-Modus" (php.net/manual/en/function.mb-detect-encoding.php#102510) - Es sollte angemerkt werden, dass die Funktion geschrieben in der Frage NICHT eigentlich erkennen, ob ein beliebiger string gültiges UTF-8. Es erkennt nur wenn der string ENTHÄLT "nicht-ascii multibyte-Sequenzen in UTF-8-Reihe". Also ein reiner ascii-string wie "hello world" würde der test als nicht bestanden. Siehe meine Antwort unten für eine detaillierte Erklärung, wo diese Funktion kam.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie nicht wissen die Codierung einer Zeichenkette, ist es unmöglich, daß die Codierung mit jedem Grad der Genauigkeit. Das ist, warum
mb_detect_encoding
einfach nicht funktioniert. Wenn Sie jedoch wissen, mit welchem encoding einen string sollte sein, können Sie prüfen, ob es sich um eine gültige Zeichenfolge Codierung mitmb_check_encoding
. Mehr oder weniger tut, was dein regex funktioniert, wahrscheinlich ein wenig mehr umfassend. Es kann die Frage beantworten "Ist diese Sequenz von bytes gültig in UTF-8?" mit einem klaren ja oder Nein. Das muss nicht unbedingt bedeuten, das der string tatsächlich ist codiert, die Codierung, sondern nur, dass es sein kann. Zum Beispiel, es wird unmöglich sein, zu unterscheiden, alle single-byte-Codierung über alle 8 bits von jedem anderen single-byte-Codierung mit 8 bits. Aber UTF-8 sollte eher erkennbar ist, wenn Sie produzieren können, zum Beispiel Latin-1-kodierte strings, der nebenbei auch gültiges UTF-8-byte-Sequenzen.Kurzum, es gibt keine Möglichkeit, sicher zu wissen. Wenn Sie erwarten, dass UTF-8, überprüfen Sie, ob die byte-Sequenz, die Sie erhalten ist gültig in UTF-8, dann gönnen Sie den string sicher als UTF-8. Darüber hinaus gibt es kaum etwas, was Sie tun können.
mb_check_encoding
sagt, es ist gültig in einem bestimmten encoding, dann ist es! Sie sind alle gleichermaßen gültig! Treffen Sie Ihre Wahl! Tests für ASCII-und wenn es nicht gelingt, Sie davon ausgehen, es ist ASCII-dennoch macht keinen Sinn überhaupt.Gut, es wird nur geprüft, wenn der string byte-Sequenzen, die zufällig entsprechen gültigen UTF-8-Codepunkte. Jedoch, es wird nicht die Flagge der Sequenz 0x00-0x7F (ASCII-kompatible Teilmenge von UTF-8.
EDIT: Übrigens, ich nehme an, der Grund, dachte
mb_detect_encoding()
"ging nicht richtig" war, denn Ihr Latin-1 codierte Datei nur die ASCII-kompatible Teilmenge, die auch gültig ist in UTF-8. Es ist kein Wunder, dassmb_detect_encoding()
würde-flag, das als UTF-8 und es ist "richtig", wenn die Daten nur ASCII, dann ist die Antwort UTF-8 ist so gut wie Latin-1 oder ASCII oder einer der vielen erweiterten ASCII-Codierungen.Wird nur erkannt, wenn ein Teil der string eine formal gültige UTF-8-Sequenz, ignorieren eine code-Einheit-codierte Zeichen (Darstellung von code-points in ASCII). Für diese Funktion den Wert true zurück, und es genügt, dass es einen Charakter, der aussieht wie ein nicht-ASCII-UTF-8-codierten Zeichen.
Im Grunde nicht.
mb_detect_encoding
ist, in der Tat, zu korrigieren, indem Sie sagen, so. Und Nein, Sie werden keine Probleme haben, mit ASCII-text als UTF-8. Es ist der Grund, UTF8 arbeitet in den ersten Platz.Soweit ich das verstanden habe, die Funktion, die Sie geliefert wird nicht überprüft, ob Gültigkeit der string, nur, dass es enthält einige Sequenzen, die zufällig ähnlich denen von UTF8, damit diese Funktion könnte Fehlzündung viel schlimmer. Sie möchten möglicherweise verwenden Sie diese Funktion und
mb_detect_encoding
im strikten Modus und hoffe, dass Sie Abbrechen aus jeder anderen false-positives.Wenn der text geschrieben ist, in einem nicht-lateinischen alphabet, eine "intelligente" Weise zu erkennen, eine multibyte-Kodierung ist, für Sequenzen von gleich großen Blöcken von bytes beginnend mit dem gleichen bits. Zum Beispiel, Russischen Wort "привет" sieht so aus:
Diese allerdings nicht für Latein-basierte Alphabete (und, wahrscheinlich, Chinesisch).
Die Funktion in Frage (die, die der Benutzer pilif veröffentlicht in der verlinkten Frage) scheint, gewesen genommen von dieser Kommentar auf die
mb_detect_encoding()
Seite im PHP-Handbuch:Als der Autor erklärt, die Funktion ist nur dazu da, zu "überprüfen, ob ein string enthält UTF-8-Zeichen" und es sieht nur für "nicht-ascii multibyte-Sequenzen in UTF-8-Reihe". Daher gibt die Funktion false (null eigentlich), wenn dein string enthält nur einfache ascii-Zeichen (z.B. englischer text), das ist wahrscheinlich nicht das, was Sie wollen.
Seine Funktion wurde auf der Basis einer anderen Funktion in diese vorherigen Kommentar auf die gleiche Seite, die ist, in der Tat, bedeutete, zu überprüfen, ob ein string ist UTF-8 und wurde basierend auf dieser reguläre Ausdruck von jemandem erstellt bei W3C.
Hier ist das original, richtig funktioniert (habe ich getestet) - Funktion, die Ihnen sagen, ob ein string ist UTF-8:
mb_detect_encoding()
ist, dass es unterstützt nicht die "Mac OS Roman" (oder "macintosh") - Zeichensatz, der ist noch etwas, das Häufig für OS X. Es wird nicht richtig identifizieren es als UTF-8.Dies ist vielleicht nicht die Antwort auf Ihre Frage (vielleicht ist es, siehe update unten), aber es könnte die Antwort auf Ihr problem. Überprüfen Sie heraus meine Encoding-Klasse, die Methoden zur Umwandlung von Zeichenketten in UTF8, egal ob Sie codiert sind, in Latin1, Win1252, oder UTF8 bereits, oder eine Mischung von Ihnen:
https://stackoverflow.com/a/3479832/290221
Die Funktion ausgeführt wird byte für byte und herauszufinden, ob jede von Ihnen erfordert die Konvertierung oder nicht.
Update:
Denken ein bisschen mehr darüber, könnte dies in der Tat die Antwort auf Ihre Frage:
Und hier ist die Encoding-Klasse:
https://github.com/neitanod/forceutf8
if (!mb_check_encoding($str, 'UTF-8')) $str = iconv('ISO-8859-1', 'UTF-8', $str)
. Hinzufügen einespreg_match
check für typische Windows-1252 byte-Sequenzen zu Versuch zu differenzieren zwischen ISO-8859-1 und Windows-1252, das wird nie 100% genau. Anstatt das zu tun, alle, die, wären Sie besser dran, zu wissen, Ihre Codierungen.Encoding::toUTF8
hat das gleiche problem wieutf8_encode
: Er suggeriert etwas, was nicht stimmt, ist, dass Sie brauchen nicht zu denken über die Kodierungen. Ich würde immer eher ablehnen ungültige Codierungen und versuchen Sie, die Anbieter, um Sie zu beheben, als zu versuchen, mit zerbrochenen Dokumente. Versucht auto-detection und best-guess-Konvertierung ist ein letzter Ausweg, kein normaler modus operandi.