c # von Byte-Array Detect XML-Codierung?
-
06-09-2019 - |
Frage
Nun, ich habe einen Byte-Array, und ich weiß, es ist ein xml serilized Objekt in dem Byte-Array ist es eine Möglichkeit, die Codierung von ihm zu bekommen?
Im gehend deserilize es nicht, aber ich bin es in einem XML-Feld auf einem SQL Server-Speicher ... so muß ich es in eine Zeichenfolge konvertieren?
Lösung
könnten Sie schauen auf den ersten 40-ish Bytes 1 . Sie sollte enthalten die Dokumentdeklaration (vorausgesetzt, es hat ein Dokument Erklärung), die entweder die Kodierung enthalten sollte oder können Sie es annehmen, ist UTF-8 oder UTF-16, die von offensichtlich sein sollte sollte, wie Sie das <?xml
Teil verstanden haben. (Stellt sicher für beide Muster.)
Realistisch betrachtet, erwarten Sie, die Sie jemals etwas anderes als UTF-8 erhalten oder UTF-16? Wenn nicht, könnten Sie für die Muster überprüfen Sie zu Beginn der diese beiden erhalten und eine Ausnahme auslösen, wenn es nicht so oder Muster folgt. Alternativ, wenn Sie einen neuen Versuch machen wollen, können Sie immer versuchen, das Dokument als UTF-8, neu kodieren, sie zu entschlüsseln und sehen, ob Sie das gleiche Bytes zurück. Es ist nicht ideal, aber es könnte funktionieren.
Ich bin sicher, dass es strengere Wege, dies zu tun, aber sie sind wahrscheinlich pingelig sein:)
1 Durchaus möglich weniger als diese. Ich stelle dar 20 Zeichen sollte genug sein, die 40 Bytes in UTF-16 ist.
Andere Tipps
Eine Lösung ähnlich href="https://stackoverflow.com/questions/637855/how-to-best-detect-encoding-in-xml-file"> diese Frage diese lösen könnten durch einen Strom über das Byte-Array verwendet wird. Dann werden Sie nicht auf Byte-Ebene zur Geige haben. Wie folgt aus:
Encoding encoding;
using (var stream = new MemoryStream(bytes))
{
using (var xmlreader = new XmlTextReader(stream))
{
xmlreader.MoveToContent();
encoding = xmlreader.Encoding;
}
}
Die ersten 2 oder 3 Bytes kann ein Byte Order Mark (BOM) sein, was man kann sagen, ob der Stream UTF-8, Unicode-LittleEndian oder Unicode-BigEndian.
UTF-8 BOM ist 0xEF 0xBB 0xBF Unicode-bigEndian ist 0xFE 0xFF Unicode-LittleEndiaon ist 0xFF 0xFE
Wenn keine dieser vorhanden sind, dann können Sie ASCII verwenden für <?xml
zu testen (beachten Sie modernsten XML-Generation-Sticks auf den Standard, dass kein weißer Raum, um die XML-declare vorangestellt werden kann).
ASCII, bis ?>
verwendet, so dass Sie das Vorhandensein von Codierung finden = und seinen Wert finden.
Wenn Codierung nicht vorhanden oder <?xml
declare ist nicht vorhanden ist, dann können Sie davon ausgehen, UTF-8.
Die W3C XML-Spezifikation einen Abschnitt darauf hat, wie die Codierung zu bestimmen, eine Bytestring.
Überprüfen Sie zunächst für eine Unicode-Byte Order Mark
Eine BOM ist nur ein weiteres Zeichen; es ist das:
Das Zeichen U + FEFF , zusammen mit allen anderen Zeichen in der Datei codiert wird, das entsprechende Codierungsschema unter Verwendung von:
-
00 00 FE FF
: UCS-4, Big-Endian-Maschine (1234 Reihenfolge) -
FF FE 00 00
: UCS-4, Little-Endian-Maschine (4321 Reihenfolge) -
00 00 FF FE
: UCS-4, ungewöhnliche Oktett Ordnung (2143) -
FE FF 00 00
: UCS-4, ungewöhnliche Oktett Ordnung (3412) -
FE FF ## ##
: UTF-16, Big-Endian -
FF FE ## ##
: UTF-16, Little-Endian -
EF BB BF
: UTF-8
wo ## ##
kann alles sein - außer für die beide null
So überprüfen Sie zuerst die inital Bytes für jede dieser Signaturen. Wenn Sie einen von ihnen, Rückkehr finden, die a href <= "https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx?f=255&MSPPError= -2147217396" rel = "noreferrer"> Code-Seitenbezeichnerliste
UInt32 GuessEncoding(byte[] XmlString)
{
if BytesEqual(XmlString, [00, 00, $fe, $ff]) return 12001; //"utf-32BE" - Unicode UTF-32, big endian byte order
if BytesEqual(XmlString, [$ff, $fe, 00, 00]) return 1200; //"utf-32" - Unicode UTF-32, little endian byte order
if BytesEqual(XmlString, [$fe, $ff, 00, 00]) throw new Exception("Nobody supports 2143 UCS-4");
if BytesEqual(XmlString, [$fe, $ff, 00, 00]) throw new Exception("Nobody supports 3412 UCS-4");
if BytesEqual(XmlString, [$fe, $ff])
{
if (XmlString[2] <> 0) && (XmlString[3] <> 0)
return 1201; //"unicodeFFFE" - Unicode UTF-16, big endian byte order
}
if BytesEqual(XmlString, [$ff, $fe])
{
if (XmlString[2] <> 0) && (XmlString[3] <> 0)
return 1200; //"utf-16" - Unicode UTF-16, little endian byte order
}
if BytesEqual(XmlString, [$ef, $bb, $bf]) return 65001; //"utf-8" - Unicode (UTF-8)
Oder für aussehen: Xml
Wenn das XML-Dokument keinen Byte Order Mark Charakter hat, dann bewegen Sie sich für die ersten fünf Zeichen zu suchen auf, die jedes XML-Dokument haben muss:
<?xml
Es ist hilfreich zu wissen, dass
-
<
ist # x0000003C -
?
ist # x0000003F
Damit haben wir genug in den ersten vier Bytes aussehen:
-
00 00 00 3C
: UCS-4, Big-Endian-Maschine (1234 Reihenfolge) -
3C 00 00 00
: UCS-4, Little-Endian-Maschine (4321 Reihenfolge) -
00 00 3C 00
: UCS-4, ungewöhnliche Oktett Ordnung (2143) -
00 3C 00 00
: UCS-4, ungewöhnliche Oktett Ordnung (3412) -
00 3C 00 3F
: UTF-16, Big-Endian -
3C 00 3F 00
: UTF-16, Little-Endian -
3C 3F 78 6D
: UTF-8 -
4C 6F A7 94
: einige Geschmack von EBCDIC
So können wir dann mehr in unserem Code:
if BytesEqual(XmlString, [00, 00, 00, $3C]) return 12001; //"utf-32BE" - Unicode UTF-32, big endian byte order
if BytesEqual(XmlString, [$3C, 00, 00, 00]) return 1200; //"utf-32" - Unicode UTF-32, little endian byte order
if BytesEqual(XmlString, [00, 00, $3C, 00]) throw new Exception("Nobody supports 2143 UCS-4");
if BytesEqual(XmlString, [00, $3C, 00, 00]) throw new Exception("Nobody supports 3412 UCS-4");
if BytesEqual(XmlString, [00, $3C, 00, $3F]) return return 1201; //"unicodeFFFE" - Unicode UTF-16, big endian byte order
if BytesEqual(XmlString, [$3C, 00, $3F, 00]) return 1200; //"utf-16" - Unicode UTF-16, little endian byte order
if BytesEqual(XmlString, [$3C, $3F, $78, $6D]) return 65001; //"utf-8" - Unicode (UTF-8)
if BytesEqual(XmlString, [$4C, $6F, $A7, $94])
{
//Some variant of EBCDIC, e.g.:
//20273 IBM273 IBM EBCDIC Germany
//20277 IBM277 IBM EBCDIC Denmark-Norway
//20278 IBM278 IBM EBCDIC Finland-Sweden
//20280 IBM280 IBM EBCDIC Italy
//20284 IBM284 IBM EBCDIC Latin America-Spain
//20285 IBM285 IBM EBCDIC United Kingdom
//20290 IBM290 IBM EBCDIC Japanese Katakana Extended
//20297 IBM297 IBM EBCDIC France
//20420 IBM420 IBM EBCDIC Arabic
//20423 IBM423 IBM EBCDIC Greek
//20424 IBM424 IBM EBCDIC Hebrew
//20833 x-EBCDIC-KoreanExtended IBM EBCDIC Korean Extended
//20838 IBM-Thai IBM EBCDIC Thai
//20866 koi8-r Russian (KOI8-R); Cyrillic (KOI8-R)
//20871 IBM871 IBM EBCDIC Icelandic
//20880 IBM880 IBM EBCDIC Cyrillic Russian
//20905 IBM905 IBM EBCDIC Turkish
//20924 IBM00924 IBM EBCDIC Latin 1/Open System (1047 + Euro symbol)
throw new Exception("We don't support EBCDIC. Sorry");
}
//Otherwise assume UTF-8, and fail to decode it anyway
return 65001; //"utf-8" - Unicode (UTF-8)
//Any code is in the public domain. No attribution required.
}