سؤال

حسنا، لدي صفيف بايت، وأنا أعلم أن كائن ساري XML في صفيف البايت هو هناك أي طريقة للحصول على الترميز منه؟

أنا لن أحلامها ولكني حفظها في حقل XML على خادم SQL ... لذلك أحتاج إلى تحويله إلى سلسلة؟

هل كانت مفيدة؟

المحلول

يمكنك أن تنظر إلى البايت الأربعين الأولين1. وبعد هم ينبغي تحتوي على إعلان المستند (على افتراض ذلك لديها إعلان مستند) الذي يجب أن يحتوي إما على الترميز أو يمكنك افتراض أنه UTF-8 أو UTF-16، والذي ينبغي أن يكون واضحا من كيفية فهمك <?xml جزء. (فقط تحقق من كلا الأنماط.)

واقعية، هل تتوقع أن تحصل على أي شيء آخر غير UTF-8 أو UTF-16؟ إذا لم يكن الأمر كذلك، فيمكنك التحقق من الأنماط التي تحصل عليها في بداية كل من تلك ورمي استثناء إذا لم يتبع النمط. بدلا من ذلك، إذا كنت ترغب في إجراء محاولة أخرى، فيمكنك دائما محاولة فك تشفير المستند باسم UTF-8، وإعادة تشفيرها ومعرفة ما إذا كنت تحصل على نفس البايتات. انها ليست مثالية، ولكن قد تعمل فقط.

أنا متأكد من أن هناك طرق أكثر صرامة للقيام بذلك، لكن من المحتمل أن تكون أخيرا :)


1 ربما أقل من هذا. يجب أن يكون الرقم 20 حرفا كافيا، وهو 40 بايت في UTF-16.

نصائح أخرى

حل مشابه ل هذا السؤال يمكن حل هذا باستخدام دفق على صفيف البايت. ثم لن تضطر إلى كمان على مستوى البايت. مثله:

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-Linkode-Linkode أو Unicode-Bigendian.

UTF-8 Bom هو 0xEF 0xbb 0xbf Unicode-Bigendian هو 0xff 0xff Unicode-Linterendiaon هو 0xff 0xfe

إذا لم يكن أي من هذه حاضرين، فيمكنك استخدام ASCII لاختبار <?xml (لاحظ أن معظم جيل XML الحديث يتمسك بالمعيار الذي لا يمكن لأي مسافة بيضاء مسبق تعلن XML).

يستخدم ASCII حتى ?> حتى تتمكن من العثور على وجود الترميز = وابحث عن قيمتها. إذا الترميز غير موجود أو <?xml يعلن غير موجود، يمكنك افتراض UTF-8.

ال مواصفات W3C XML لديها قسم حول كيفية تحديد ترميز سلسلة البايت.

تحقق أولا من علامة ترتيب البايت Unicode

بوم هو مجرد شخصية أخرى؛ انها ال:

"عرض صفر لا تتراجع مساحة" (U + FEFF)

الشخصية U + FEFF., ، إلى جانب كل حرف آخر في الملف، يتم ترميزه باستخدام نظام الترميز المناسب:

  • 00 00 FE FF: UCS-4، آلة كبيرة الانديان (1234 طلب)
  • FF FE 00 00: UCS-4، آلة Little-Endian (4321 Order)
  • 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، آلة Little-Endian (4321 Order)
  • 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.
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top