Erkennung einer fehlerhaften UTF-8-Kodierung: Liste der zu schnüffelnden schlechten Zeichen?

9

Ich habe eine sql-server 2010-Datenbank zwischen zwei Anwendungen geteilt. Eine Anwendung, die wir kontrollieren können, und die andere Anwendung ist eine Drittanbieter-App, die die Datenbank überhaupt erstellt hat. Unsere App ist ein CRM, das auf der Webmail-App von Drittanbietern aufbaut.

Die Datenbank enthält varchar-Spalten und ist latin-1-codiert. Die App von Drittanbietern ist in PHP geschrieben und kümmert sich nicht darum, die Daten korrekt zu kodieren, also stopft sie utf-8-codierte Bytes in die varchar-Spalten, wo sie als latin-1 interpretiert werden und wie Müll aussehen.

Unsere CRM-App ist in .Net geschrieben, was automatisch erkennt, dass die Datenbanksortierung sich von der Codierung der Zeichenfolge im Speicher unterscheidet. Wenn .Net also in eine Datenbank schreibt, werden die Bytes entsprechend der Datenbankcodierung konvertiert / p>

Also ... Daten, die von unserer App in die db geschrieben werden, sehen in der db korrekt aus, aber Daten aus der Drittanbieter-App nicht.

Wenn unsere App FirstName = Céline schreibt, wird sie in der Datenbank als Céline

gespeichert

Wenn die Webmail-App FirstName = Céline schreibt, wird sie in der Datenbank als Céline

gespeichert

Unsere CRM-App muss Kontakte anzeigen, die in beiden Systemen erstellt wurden. Ich schreibe eine EncodingSniffer-Klasse, die nach markierten Zeichen sucht, die auf eine schlecht codierte Zeichenfolge hinweisen, und sie konvertiert.

momentan habe ich:

%Vor%

was großartig für die Anzeige von Céline als Céline ist, aber ich muss der Liste hinzufügen.

Kennt jemand eine Ressource, um alle möglichen Möglichkeiten zu bekommen, dass utf-8 spezielle Zeichen als iso-8859-1 interpretiert werden könnten?

Danke

 Klärung: Seit ich in .Net arbeite. Wenn die Zeichenfolge aus der Datenbank in den Speicher geladen wird, wird sie in Unicode UTF-16 konvertiert. Also, egal ob es richtig in der Datenbank kodiert wurde. Es wird jetzt als UTF16 Bytes dargestellt. Ich muss in der Lage sein, diese UTF-16 Bytes zu analysieren, und festzustellen, ob sie wegen utf-8 Bytes, die in eine iso-8859-1-Datenbank gestopft werden, vermasselt werden ... klar wie Schlamm, richtig?

Hier ist was ich bisher habe. Es hat die Anzeige der meisten miscodierten Charaktere aufgeräumt, aber ich habe immer noch Probleme mit É Zum Beispiel: Éric wird in der db per Webmail als Ãœberschrift gespeichert, aber nachdem er eine schlechte Codierung erkannt und wieder zurückverwandelt hat, wird sie als Ãœberschrift angezeigt Betrachtet man einen Benutzer, der 2500 Kontakte hat, von denen Hunderte Kodierungsprobleme hatten, ist die É die einzige Sache, die nicht richtig angezeigt wird ...

%Vor%

Also: É wird in 195 'umgewandelt, 8240' ‰ '

    
Michael 07.05.2012, 15:32
quelle

2 Antworten

0

Sie sollten wahrscheinlich versuchen, die Byte-Zeichenfolge als UTF-8 zu dekodieren, und wenn Sie einen Fehler erhalten, nehmen Sie stattdessen an, dass es ISO-8859-1 ist.

Text, der als ISO-8859-1 kodiert ist, "passiert" selten auch als gültiges UTF-8 ... es sei denn, es ist ISO-8859-1, das nur tatsächlich ASCII enthält, aber in diesem Fall haben Sie nicht natürlich ein Problem. Diese Methode ist also einigermaßen robust.

Wenn Sie ignorieren, welche Zeichen in der aktuellen Sprache häufiger vorkommen als andere, ist dies eine naive Analyse, bei der davon ausgegangen wird, dass jedes Zeichen mit derselben Häufigkeit auftritt. Versuchen wir herauszufinden, wie oft ISO-8859-1 mit UTF-8 verwechselt werden kann, was zu Mojibake führt. Ich nehme auch an, dass C1-Steuerzeichen (U + 0080 bis U + 009F) nicht auftreten.

Für jedes gegebene Byte in der Bytefolge. Wenn sich das Byte nahe am Ende der Zeichenfolge befindet, ist es sogar noch wahrscheinlicher, dass falsch formatierte UTF-8 erkannt wird, da einige Bytefolgen nicht lange genug sind, um gültiges UTF-8 zu sein. Aber angenommen, das Byte ist nicht nahe am Ende der Zeichenfolge:

  • p (Byte dekodiert als ASCII) = 0,57. Dies gibt keine Informationen darüber, ob die Zeichenfolge ASCII, ISO-8859-1 oder UTF-8 ist.
  • Wenn dieses Byte 0x80 bis 0xc1 oder 0xf8 bis 0xff ist, kann es nicht UTF-8 sein, also werden Sie das erkennen. p = 0,33
  • Wenn dieses erste Byte 0xc2 bis 0xdf (p = 0,11) ist, dann könnte es UTF-8 sein, aber nur wenn ein Byte mit einem Wert zwischen 0x80 und 0xbf folgt. Die Wahrscheinlichkeit, dass das nächste Byte nicht in diesem Bereich liegt, ist 192/224 = 0.86. Die Wahrscheinlichkeit, dass UTF-8 hier ausfällt, beträgt also 0,09
  • Wenn das erste Byte 0xe0 bis 0xef ist, dann könnte es UTF-8 sein, aber nur, wenn ihm 2 Fortsetzungsbytes folgen. Die Wahrscheinlichkeit, dass Sie schlechtes UTF-8 entdecken, ist also (16/224) * (1- (0,14 * 0,14)) = 0,07
  • Ähnlich wie für 0xf0 bis 0xf7 ist die Wahrscheinlichkeit (8/224) * (1- (0.14 * 0.14 * 0.14)) = 0.04.

Bei jedem Byte in einer langen Zeichenfolge beträgt die Wahrscheinlichkeit, schlechtes UTF-8 zu erkennen, 0,33 + 0,09 + 0,07 + 0,04 = 0,53.

Für eine lange Zeichenfolge ist die Wahrscheinlichkeit, dass ISO-8859-1 lautlos durch einen UTF-8-Decoder läuft, sehr klein: Sie ist ungefähr halbiert für jedes zusätzliche Zeichen!

Diese Analyse setzt natürlich zufällige ISO-8859-1-Zeichen voraus. In der Praxis wird die Fehldetektionsrate nicht ganz so gut sein (hauptsächlich aufgrund der Tatsache, dass die meisten Bytes im realen Text tatsächlich ASCII sind), aber es wird immer noch sehr gut sein.

    
Celada 07.05.2012 16:28
quelle
0

Danke @Michael für über 99% der Arbeit!

Hier ist eine PowerShell-Version von Michaels Skript für jeden, dem es hilft. Dies auch @ Qubei's Vorschlag der Windows-1252 code page / encoding um das É issue zu lösen; Sie können diese Kodierungen jedoch ändern, falls Ihre Daten durch eine andere Kombination von Kodierungen beschädigt wurden.

%Vor%

Demo

%Vor%

Zusätzliche Funktion in meiner Demo verwendet

Ich bin kein Fan des Invoke-SqlCmd Cmdlet, also habe ich mein eigenes gerollt.

%Vor%     
JohnLBevan 09.08.2017 16:47
quelle

Tags und Links