2012-07-28 20 views
22

.NETでは、Encoding.UTF8.GetStringメソッドを使用しようとしています。これはバイト配列をとり、stringに変換します。Encoding.UTF8.GetStringはプリアンブル/ BOMを考慮していません

このメソッドは、BOM (Byte Order Mark)(UTF8文字列の正当なバイナリ表現の一部である可能性があります)を無視し、文字として扱います。

私はTextReaderを使用して必要に応じてBOMをダイジェストすることができますが、私はGetStringメソッドをコードを短くする種類のマクロにする必要があると考えました。

何か不足していますか?これはそんなに意図的ですか?ここで

は、再生コードです:

static void Main(string[] args) 
{ 
    string s1 = "abc"; 
    byte[] abcWithBom; 
    using (var ms = new MemoryStream()) 
    using (var sw = new StreamWriter(ms, new UTF8Encoding(true))) 
    { 
     sw.Write(s1); 
     sw.Flush(); 
     abcWithBom = ms.ToArray(); 
     Console.WriteLine(FormatArray(abcWithBom)); // ef, bb, bf, 61, 62, 63 
    } 

    byte[] abcWithoutBom; 
    using (var ms = new MemoryStream()) 
    using (var sw = new StreamWriter(ms, new UTF8Encoding(false))) 
    { 
     sw.Write(s1); 
     sw.Flush(); 
     abcWithoutBom = ms.ToArray(); 
     Console.WriteLine(FormatArray(abcWithoutBom)); // 61, 62, 63 
    } 

    var restore1 = Encoding.UTF8.GetString(abcWithoutBom); 
    Console.WriteLine(restore1.Length); // 3 
    Console.WriteLine(restore1); // abc 

    var restore2 = Encoding.UTF8.GetString(abcWithBom); 
    Console.WriteLine(restore2.Length); // 4 (!) 
    Console.WriteLine(restore2); // ?abc 
} 

private static string FormatArray(byte[] bytes1) 
{ 
    return string.Join(", ", from b in bytes1 select b.ToString("x")); 
} 

答えて

18

このメソッドはUTF8文字列の正当なバイナリ表現の一部である可能性がありBOM(バイトオーダーマーク)を、無視して、それを取るように見えます文字として。

これはまったく「無視」するようには見えません。忠実にBOM文字に変換されます。結局のところ、それは何ですか。

コードで変換する任意の文字列内のBOMを無視するようにするには、それはあなた次第です...またはStreamReaderを使用してください。 StreamReader続いEncoding.GetStringまたは使用StreamWriter続くあなたがどちらか使用Encoding.GetBytes場合は、両方の形式は、どちらかの生産その後、BOMを生成飲み込むか、しないこと

は注意してください。 (Encoding.GetPreambleを使用)と「Encoding.GetString」という直接のコールを使用してミックスした場合、「余分な」文字になります。ジョンスキートによって答え(!ありがとう)に基づいて

+0

私が参照してください。解明してくれてありがとう! –

+5

@RonKleinまた、先頭のBOM文字を削除するには、 'restore2 = restore2.TrimStart( '\ uFEFF')'と言うことができます。 GetBytes( "abc") 'と'(新しいUTF8Encoding(false)).GetBytes( "abc") 'は同じ出力を生成しますが、おそらくあなたは同じ出力を生成します。今知っている 'GetBytes'はあなたがファイルの先頭にいるとは想定していないので、' GetPreamble'を使うことはありません。 'GetBytes'や' GetString'を使うと、 'GetPreamble'を明示的に、またはプリアンブルを明示的にスキップする必要があります。 –

7

が、これは私がそれをやった方法です:をバイト配列にBOMがある場合、これはおそらく唯一確実に動作することを

var memoryStream = new MemoryStream(byteArray); 
var s = new StreamReader(memoryStream).ReadToEnd(); 

は注意あなたは読んでいる。そうでない場合は、another StreamReader constructor overloadを調べてエンコーディングパラメータを取得し、バイト配列に含まれる内容を知ることができます。

+0

私はこのコンストラクタのオーバーロード(https://msdn.microsoft.com/en-us/library/ms143457(v = vs.110).aspx)が必要かもしれないと思います。エンコーディングを把握するBOM – drzaus

0

私は一種の後期パーティーにしていますが、ここであなたが必要な場合、私は(C#のに適応して自由に感じる)を使用していたコードを知っている:

Public Function Serialize(Of YourXMLClass)(ByVal obj As YourXMLClass, 
                 Optional ByVal omitXMLDeclaration As Boolean = True, 
                 Optional ByVal omitXMLNamespace As Boolean = True) As String 

     Dim serializer As New XmlSerializer(obj.GetType) 
     Using memStream As New MemoryStream() 
      Dim settings As New XmlWriterSettings() With { 
        .Encoding = Encoding.UTF8, 
        .Indent = True, 
        .OmitXmlDeclaration = omitXMLDeclaration} 

      Using writer As XmlWriter = XmlWriter.Create(memStream, settings) 
       Dim xns As New XmlSerializerNamespaces 
       If (omitXMLNamespace) Then xns.Add("", "") 
       serializer.Serialize(writer, obj, xns) 
      End Using 

      Return Encoding.UTF8.GetString(memStream.ToArray()) 
     End Using 
    End Function 

Public Function Deserialize(Of YourXMLClass)(ByVal obj As YourXMLClass, ByVal xml As String) As YourXMLClass 
     Dim result As YourXMLClass 
     Dim serializer As New XmlSerializer(GetType(YourXMLClass)) 

     Using memStream As New MemoryStream() 
      Dim bytes As Byte() = Encoding.UTF8.GetBytes(xml.ToArray) 
      memStream.Write(bytes, 0, bytes.Count) 
      memStream.Seek(0, SeekOrigin.Begin) 

      Using reader As XmlReader = XmlReader.Create(memStream) 
       result = DirectCast(serializer.Deserialize(reader), YourXMLClass) 
      End Using 

     End Using 
     Return result 
    End Function 
関連する問題