문제

바이트 어레이가 있고 바이트 배열의 XML 톱니 모양의 물체가 인코딩을 얻는 방법이 있다는 것을 알고 있습니다.

Im은 그것을 버리지 않을 것이지만 SQL 서버의 XML 필드에 저장하고 있습니다 ... 그래서 문자열로 변환해야합니까?

도움이 되었습니까?

해결책

처음 40시 바이트를 볼 수 있습니다1. 그들 ~해야 한다 문서 선언을 포함합니다 (가정 가지다 인코딩을 포함 해야하는 문서 선언) 또는 UTF-8 또는 UTF-16이라고 가정 할 수 있습니다. <?xml 부분. (두 패턴 모두를 확인하십시오.)

현실적으로, 당신은 당신이 UTF-8 또는 UTF-16 이외의 다른 것을 얻을 것을 기대합니까? 그렇지 않다면, 두 가지 시작 부분에서 얻는 패턴을 확인하고 어느 패턴을 따르지 않으면 예외를 던질 수 있습니다. 또는 다른 시도를하려면 항상 문서를 UTF-8으로 해독하고 다시 인코딩하고 동일한 바이트를 다시 얻는 지 확인할 수 있습니다. 이상적이지는 않지만 단지 작동 할 수도 있습니다.

나는 이것을하는 더 엄격한 방법이 있다고 확신하지만, 그들은 까다로울 가능성이 높다 :)


1 이보다 훨씬 적습니다. I 그림 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 바이트는 스트림이 UTF-8, 유니 코드-리틀 엔디언 또는 유니 코드-비드 니아인지 여부를 알 수있는 바이트 차수 마크 (BOM) 일 수 있습니다.

UTF-8 BOM은 0xef 0xBB 0xBF 유니 코드-비드 니아입니다.

이 중 어느 것도 존재하지 않으면 ASCII를 사용하여 테스트 할 수 있습니다. <?xml (대부분의 최신 XML 생성은 공백이 XML 선언을 전달할 수 없다는 표준을 고수합니다).

ASCII는 전까지 사용됩니다 ?> 따라서 인코딩의 존재를 찾고 그 값을 찾을 수 있습니다. 인코딩이 존재하지 않는 경우 또는 <?xml 선언이 없으면 UTF-8을 가정 할 수 있습니다.

그만큼 W3C XML 사양에는 섹션이 있습니다 바이트 스트링의 인코딩을 결정하는 방법에 대해.

먼저 유니 코드 바이트 주문 마크를 점검하십시오

Bom은 또 다른 캐릭터입니다. 그건:

'제로 폭 너비 파괴 공간'(U+Feff)

캐릭터 u+feff, 파일의 다른 모든 문자와 함께 적절한 인코딩 체계를 사용하여 인코딩됩니다.

  • 00 00 FE FF: UCS-4, Big-Endian Machine (1234 주문)
  • FF FE 00 00: UCS-4, Little-Endian Machine (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

어디 ## ## 둘 다 0이 될 수 있습니다

따라서 먼저 해당 서명에 대해 Inital Bittes를 점검하십시오. 당신이 그들 중 하나를 찾으면 그것을 반환하십시오 코드 페이지 식별자

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 문서가 가져야 할 첫 5자를 찾는 것으로 이동합니다.

<?xml

그것을 아는 것이 도움이됩니다

  • < #x0000003c입니다
  • ? #x0000003f입니다

그것으로 우리는 처음 네 바이트를 볼 수 있습니다.

  • 00 00 00 3C: UCS-4, Big-Endian Machine (1234 주문)
  • 3C 00 00 00: UCS-4, Little-Endian Machine (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