Question

Eh bien j'ai un tableau d'octets, et je sais que un objet xml serilized dans le tableau d'octets est-il un moyen d'obtenir l'encodage de celui-ci?

Im ne va pas deserilize mais il sauver im dans un champ XML sur un serveur sql ... donc je dois le convertir en une chaîne?

Était-ce utile?

La solution

Vous pouvez regarder les premiers octets 40 ish 1 . Ils devraient contenir la déclaration de documents (en supposant que a une déclaration de document) qui doit contenir soit le codage ou vous pouvez supposer qu'il est UTF-8 ou UTF-16, qui devrait devrait être évident de la façon dont vous avez compris la partie <?xml. (Juste pour vérifier les deux modèles.)

De façon réaliste, attendez-vous que vous aurez jamais obtenir autre chose que UTF-8 ou UTF-16? Sinon, vous pouvez vérifier les modèles que vous obtenez au début des deux personnes et lancer une exception si elle ne suit pas non plus tendance. Sinon, si vous voulez faire une autre tentative, vous pouvez toujours essayer de décoder le document au format UTF-8, réencoder et voir si vous obtenez les mêmes octets en arrière. Ce n'est pas idéal, mais ça pourrait fonctionner.

Je suis sûr qu'il existe des moyens plus rigoureux de le faire, mais ils sont susceptibles d'être pointilleux:)


1 Très probablement moins que cela. Je figure 20 caractères doivent être suffisamment, ce qui est de 40 octets en UTF-16.

Autres conseils

Les 2 ou 3 premiers octets peut être un Byte Order Mark (BOM) qui peut vous dire si le flux est UTF-8, Unicode-littleEndian ou Unicode bigEndian.

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

Si aucune de ces derniers sont présents, vous pouvez utiliser ASCII pour tester <?xml (note la plupart des clés de génération XML moderne au standard pas d'espace blanc peut Preced le déclarer xml).

ASCII est utilisé jusqu'à ?> afin que vous puissiez trouver la présence de encoding = et trouver sa valeur. Si le codage est pas présent ou déclarer <?xml n'est pas présent, alors vous pouvez supposer UTF-8.

Le spécification XML du W3C a une section sur la façon de déterminer l'encodage d'une chaîne d'octets.

Vérifiez d'abord pour un Unicode Byte Order Mark

Une nomenclature est juste un autre caractère; c'est le:

  

'ZERO WIDTH ESPACE SANS COUPURE' (U + FEFF)

Le caractère U + FEFF , ainsi que tous les autres caractères dans le fichier, est codé en utilisant le schéma de codage approprié:

  • 00 00 FE FF : UCS-4, la machine big-endian (1234 commande)
  • FF FE 00 00 : UCS-4, la machine little-endian (4321 commande)
  • 00 00 FF FE : UCS-4, ordre inhabituel octet (2143)
  • FE FF 00 00 : UCS-4, ordre inhabituel octet (3412)
  • FE FF ## ## : UTF-16, big-endian
  • FF FE ## ## : UTF-16, little-endian
  • EF BB BF : UTF-8

## ## peut être quelque chose - sauf pour les deux étant zéro

Alors d'abord vérifier les octets inital pour l'une de ces signatures. Si vous trouvez l'un d'eux, le retour que identificateur de code

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)

Ou bien cherchez

Si le document XML n'a pas d'ordre d'octets caractère Mark, vous passez à la recherche pour les cinq premiers caractères que chaque document XML doit avoir:

  

<?xml

Il est utile de savoir que

  • < est # x0000003C
  • ? est # x0000003F

que nous avons assez de regarder les quatre premiers octets:

  • 00 00 00 3C : UCS-4, la machine big-endian (1234 commande)
  • 3C 00 00 00 : UCS-4, la machine little-endian (4321 commande)
  • 00 00 3C 00 : UCS-4, ordre inhabituel octet (2143)
  • 00 3C 00 00 : UCS-4, ordre inhabituel octet (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 peu de saveur de EBCDIC

Nous pouvons ajouter à notre 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.
}

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top