Domanda

Beh io ho un array di byte, e so che la sua un oggetto serilized XML nella matrice di byte C'è un modo per ottenere la codifica da esso?

Im non andando a deserilize ma Im salvandolo in un campo XML su un server SQL ... quindi ho bisogno di convertirlo in una stringa?

È stato utile?

Soluzione

Si potrebbe guardare i primi byte 40-ish 1 . Essi dovrebbe contenere la dichiarazione di documento (ammesso che ha di una dichiarazione di documento), che dovrebbe contenere sia la codifica o si può presumere che sia UTF-8 o UTF-16, che dovrebbe dovrebbe essere evidente da come avete capito la parte <?xml. (Basta controllare per entrambi i modelli.)

Realisticamente, si aspetta che tu abbia mai ottenere qualcosa di diverso da UTF-8 o UTF-16? In caso contrario, si potrebbe verificare per i modelli che si ottiene a inizio sia di quelli e un'eccezione se non segue neanche modello. In alternativa, se si vuole fare un altro tentativo, si può sempre cercare di decodificare il documento come UTF-8, ricodificarlo e vedere se si ottengono gli stessi byte indietro. Non è l'ideale, ma potrebbe funzionare.

Sono sicuro che ci sono modi più rigorosi di fare questo, ma sono suscettibili di essere pignoli:)


1 Molto probabilmente meno di questo. Immagino 20 caratteri dovrebbero essere abbastanza, che è di 40 byte in UTF-16.

Altri suggerimenti

Una soluzione simile a questa domanda potrebbe risolvere questo utilizzando uno streaming di byte. Allora non dovrete perdere tempo a livello di byte. In questo modo:

Encoding encoding;
using (var stream = new MemoryStream(bytes))
{
    using (var xmlreader = new XmlTextReader(stream))
    {
        xmlreader.MoveToContent();
        encoding = xmlreader.Encoding;
    }
}

I primi 2 o 3 byte può essere un Byte Order Mark (BOM), che può dirvi se il flusso è UTF-8, Unicode-LittleEndian o Unicode-BigEndian.

UTF-8 BOM è 0xEF 0xBB 0xBF Unicode bigEndian è 0xFE 0xFF Unicode LittleEndiaon è 0xFF 0xFE

Se nessuno di questi sono presenti, allora si può usare ASCII per verificare <?xml (nota più bastoni moderna generazione XML al livello che nessuno spazio bianco può precedere la dichiarazione XML).

ASCII viene utilizzato fino a quando ?> in modo da poter trovare la presenza di encoding = e di trovare il suo valore. Se la codifica non è presente o <?xml declare non è presente, allora si può supporre UTF-8.

Il specifiche W3C XML ha una sezione su come determinare la codifica di una stringa di byte.

Primo controllo per un Byte Order Mark Unicode

Una distinta base è solo un altro personaggio; è il:

  

'ZERO WIDTH no-break SPACE' (U + FEFF)

Il carattere U + FEFF , con ogni altro carattere nel file, è codificato utilizzando lo schema di codifica appropriata:

  • 00 00 FE FF : UCS-4, big-endian macchina (1234 ordine)
  • FF FE 00 00 : UCS-4, little-endian macchina (4321 ordine)
  • 00 00 FF FE : UCS-4, insolito ordine ottetto (2143)
  • FE FF 00 00 : UCS-4, insolito ordine ottetto (3412)
  • FE FF ## ## : UTF-16, big-endian
  • FF FE ## ## : UTF-16, little-endian
  • EF BB BF : UTF-8

dove ## ## può essere nulla - tranne che per entrambi che sono pari a zero

Quindi, per prima cosa controllare i byte inital per uno di tali firme. Se si trova uno di loro, ritorno che code-page identificativo

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)

oppure cercare

Se il documento XML non ha alcuna Byte Order Mark carattere, quindi si passa alla ricerca per i primi cinque caratteri che ogni documento XML deve avere:

  

<?xml

E 'utile sapere che

  • < è # x0000003C
  • ? è # x0000003F

Con che abbiamo abbastanza di guardare ai primi quattro byte:

  • 00 00 00 3C : UCS-4, big-endian macchina (1234 ordine)
  • 3C 00 00 00 : UCS-4, little-endian macchina (4321 ordine)
  • 00 00 3C 00 : UCS-4, insolito ordine ottetto (2143)
  • 00 3C 00 00 : UCS-4, insolito ordine ottetto (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 : un certo sapore di EBCDIC

Quindi possiamo poi aggiungere di più per il nostro codice:

   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.
}

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top