好吧,我有一个字节数组,并且我知道它是字节数组中的 xml 序列化对象,有什么方法可以从中获取编码吗?

我不会反序列化它,但我将它保存在 sql 服务器上的 xml 字段中......所以我需要将它转换为字符串?

有帮助吗?

解决方案

您可以看第一40上下的字节 1 。它们包含文档声明(假设它的具有一个文档声明),其都应包含编码可以假定它是UTF-8或UTF-16,这应该应该从你是如何理解<?xml部分明显。 (只是检查两个图案。)

实际上,你希望你永远得到比UTF-8或UTF-16其他什么吗?如果没有,你可以检查你在这两个的开始的图案并抛出一个异常,如果它不遵循任何模式。另外,如果您想再次尝试,你总是可以尝试将文档作为UTF-8解码,重新编码,看看你是否得到相同的字节后面。它的效果并不理想,但它可能只是工作。

我敢肯定有这样做的更严格的办法,但他们很可能是挑剔的:)


1 很有可能比这少。我想,20个字符应足够,这是UTF-16 40个字节。

其他提示

类似的溶液来这个问题可能解决这个通过使用流过字节数组。然后,你不会有字节级的拨弄。像这样:

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

前2或3个字节可以是字节顺序标记(BOM),它可以告诉你流是否是UTF-8,Unicode的LittleEndian或Unicode的大尾端。

UTF-8 BOM是0xEF为0xBB为0xBF Unicode的大尾端是0xFE的0xFF的 Unicode的LittleEndiaon为0xFF 0xFE的

如果这些都不存在,那么你可以使用ASCII来测试<?xml(注意最先进的XML生成粘在标准没有空格可以preceed的XML声明)。

ASCII被用尽直到?>这样你可以找到编码的存在=并找到它的值。 如果编码是不存在或<?xml申报不存在,则可以假定UTF-8。

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

首先检查 Unicode 字节顺序标记

BOM 只是另一个字符;这是:

“零宽度无中断空间”(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,大端字节序
  • FF FE ## ##: UTF-16,小尾数法
  • 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 文档必须具有的前五个字符:

<?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,大端字节序
  • 3C 00 3F 00: UTF-16,小尾数法
  • 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.
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top