1

.net ASCIIEncodingクラスを使用してバイト配列を文字列にデコードする場合、バイト順序マークを検出して削除するコードを記述する必要がありますか、それともバイト順序マークを文字列にデコードしないようにASCIIEncodingに指示することはできますか?

これを行うときの私の問題は次のとおりです。

string someString = System.Text.ASCIIEncoding.Default.GetString(someByteArray)

someStringは次のようになります。

<?xml version="1.0"?>.......

それから私がこれを呼ぶとき:

XElement.Parse(someString)

最初の3バイトが原因で例外がスローされます。EFBBBF-UTF8バイト順マーク。したがって、デフォルトではなくUTF8エンコーディングを指定すると、次のようになります。

System.Text.ASCIIEncoding.UTF8.GetString(someByteArray)

ASCIIEncodingは、バイト順序マークを文字列にデコードしようとはしませんでした。返された文字列をnotepad++にコピーすると、?が表示されます。XMLタグの前の文字。そのため、バイト順マークは単一のガベージ文字にデコードされています。この場合、バイト順マークのデコードを停止する最良の方法は何ですか?

4

3 に答える 3

5

使用しないでください

ASCIIEncoding.UTF8

それは本当にただです

Encoding.UTF8

全く使っていませんASCIIEncoding。ソースコードではそのように見えます。

基本的に、問題はファイルASCIIではなくUTF-8であるということです。そのため、UTF-8バイト順マークが付いています。いずれかの方法でUTF-8ファイルを読み取るために使用 することを強くお勧めします。Encoding.UTF8

でファイルを読み取るとFile.ReadAllText、BOMが自動的に削除されると思われます。または、後で呼び出す前にトリミングすることもできますXElement.Parse。間違ったエンコーディング(ASCIIまたはEncoding.Defaultのいずれか)を使用することは正しいアプローチではありません。同様に、それはゴミのキャラクターではありません。これは完全に便利な文字であり、実際にUTF-8ファイルであることを非常に強く示しています。この特定のコンテキストでは必要ないだけです。「ガベージ」は、ファイルに存在してはならない破損したデータであるという印象を与えますが、そうではありません。

もう1つのアプローチは、テキストへの変換をまったく回避することです。例えば:

XElement element;
using (XmlReader reader = XmlReader.Create(new MemoryStream(bytes))
{
    element = XElement.Load(reader);
}

そうすれば、エンコーディングは自動検出されます。

于 2011-02-23T23:49:47.443 に答える
2

System.Text.Encoding.GetString()BOMが存在する場合はそれを保持し、UTF-16 BOM(U + FEFF)に変換します。これを機能と考えてください。厳密に言えば、BOMをスローすると変換が不可逆になり、ラウンドトリップできなくなるため、これを行うのが適切です。ただし、目的の動作を指定するためのフラグが提供されていないのは少し驚くべきことですが、そこにあります。つまり...2つのオプションがあります:

  1. 文字列に変換し、BOMを探して削除してからXElement.Parse()、文字列を呼び出します。または...

  2. byte[]をaMemoryStreamでラップしMemoryStreamStreamReaderを使用XElement.Load()して解析を実行します。

Your choice. Here's some sample code that will work:

using System.IO;
using System.Text;
using System.Xml.Linq;

namespace TestDrive
{
    class Program
    {
        public static void Main()
        {
            byte[] octets = File.ReadAllBytes( "utf8-encoded-document-with-BOM.xml" ) ;

            // -----------------------------------------------
            // option 1: use a memory stream and stream reader
            // -----------------------------------------------
            using ( MemoryStream ms = new MemoryStream( octets) )
            using ( StreamReader sr = new StreamReader( ms , Encoding.UTF8 , true )   )
            {
                XElement element1 = XElement.Load( sr ) ;
            }

            // --------------------------------------------------------------------
            // option 2: convert to string, then look for and remove BOM if present
            // 
            // The .Net framework Encoding.GetString() methods preserve the BOM if
            // it is present. Since the internal format of .Net string is UTF-16,
            // the BOM is converted to the UTF-16 encoding (U+FEFF).
            // 
            // Consider this a feature.
            // --------------------------------------------------------------------
            // convert to UTF-16 string
            string       xml       = Encoding.UTF8.GetString( octets ) ;
            // Two different ways of getting the BOM
            //string UTF16_BOM = Encoding.Unicode.GetString(Encoding.Unicode.GetPreamble()).ToCharArray() ;
            const string UTF16_BOM = "\uFEFF" ; 
            // parse the element, removing the BOM if we see it.
            XElement element2 = XElement.Parse( xml.StartsWith( UTF16_BOM ) ? xml.Substring(1) : xml ) ;

            return ;
        }
    }
}
于 2011-02-24T00:58:07.147 に答える
1

これは答えではありませんが、コメントのコードはひどいものであり、これをあなたの質問に入れるのは少し失礼だと感じました。あなたは本当にこれをやろうとしていますか?

Byte[] bytes = new byte [] { 0xEF,0xBB,0xBF, 0x57, 0x44 };
String txt = Encoding.UTF8.GetString(bytes);
Console.WriteLine("String length {0}", txt.Length);
Console.WriteLine("String '{0}'", txt);
Console.WriteLine("Chars '{0}'", String.Join(",", txt.Select(chr => ((int)chr).ToString("x2"))));

そして、なぜあなたが得るのか疑問に思います:

String length 3
String 'WD'
String 'feff,57,44'

私は確かに...

于 2011-02-24T00:00:03.343 に答える