当前位置:  开发笔记 > 编程语言 > 正文

c#从字节数组中检测xml编码?

如何解决《c#从字节数组中检测xml编码?》经验,为你挑选了4个好方法。

好吧,我有一个字节数组,我知道它在字节数组中的xml serized对象是否有任何方法可以从中获取编码?

我不打算去除它但是我将它保存在sql server上的xml字段中......所以我需要将它转换为字符串?



1> Peter Lillev..:

类似于这个问题的解决方案可以通过在字节数组上使用Stream来解决这个问题.那么你就不必在字节级别进行操作.像这样:

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



2> Jon Skeet..:

你可以看看前40个字节1.它们应该包含文档声明(假设它一个文档声明),它应该包含编码,或者您可以假设它是UTF-8或UTF-16,这应该从您理解该部分的方式中显而易见.(只需检查两种模式.)

实际上,你是否期望你能获得除UTF-8或UTF-16以外的任何东西?如果没有,您可以检查在这两个模式开始时获得的模式,如果不遵循任何模式,则抛出异常.或者,如果您想再次尝试,可以尝试将文档解码为UTF-8,重新编码并查看是否返回相同的字节.它并不理想,但可能会起作用.

我确信有更严格的方法可以做到这一点,但它们可能很挑剔:)


1可能还不到这个.我认为20个字符应该足够了,这是UTF-16中的40个字节.



3> AnthonyWJone..:

前2或3个字节可以是字节顺序标记(BOM),它可以告诉您流是UTF-8,Unicode-LittleEndian还是Unicode-BigEndian.

UTF-8 BOM为0xEF 0xBB 0xBF Unicode-Bigendian为0xFE 0xFF Unicode-LittleEndiaon为0xFF 0xFE

如果这些都不存在,那么您可以使用ASCII进行测试(请注意,大多数现代XML生成都遵循标准,即xml声明之前不会出现空格).

ASCII被用完,直到?>你可以找到encoding =的存在并找到它的值.如果编码不存在或声明不存在,那么您可以假设UTF-8.



4> Ian Boyd..:

在W3C XML规范有一节关于如何确定一个字节字符串的编码.

首先检查Unicode字节顺序标记

BOM只是另一个角色; 这是:

'ZERO WIDTH NO-BREAK SPACE'(U + FEFF)

字符U + FEFF以及文件中的每个其他字符都使用适当的编码方案进行编码:

00 00 FE FF:UCS-4,大端机(1234订购)

FF FE 00 00:UCS-4,小端机(4321订购)

00 00 FF FE:UCS-4,不寻常的八位字节顺序(2143)

FE FF 00 00:UCS-4,不寻常的八位字节顺序(3412)

FE FF ## ##:UTF-16,big-endian

FF FE ## ##:UTF-16,little-endian

EF BB BF:UTF-8

哪里## ##可以是任何东西 - 除了两者都是零

因此,首先检查任何这些签名的初始字节.如果找到其中一个,则返回该代码页标识符

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)

或者寻找<?xml

如果XML文档没有字节顺序标记字符,那么您将继续查找每个XML文档必须具有的前五个字符:

了解这一点很有帮助

< 是#x0000003C

? 是#x0000003F

有了这个,我们就足以看到前四个字节了:

00 00 00 3C:UCS-4,大端机(1234订购)

3C 00 00 00:UCS-4,小端机(4321订购)

00 00 3C 00:UCS-4,不寻常的八位字节顺序(2143)

00 3C 00 00:UCS-4,不寻常的八位字节顺序(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:一些EBCDIC的味道

因此,我们可以在代码中添加更多内容:

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

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有