2009-06-07T23:06:06の更新内容

programming/tips/unicode_bom_netfx/index.wiki.txt

current previous
1,172 0,0
+
${smdncms:keywords,C#,Encoding,BOM,UTF,Unicode}
+
${smdncms:tags,lang/c#,api/.net}
+
*System.Text.EncodingのBOMありなしの制御
+
System.Text.Encodingを使う場合のBOMあり/なしの指定方法について。
+
#googleadunit
+

          
+
**StreamWriterでBOMが書き込まれる条件
+
MSDNの[[StreamWriterコンストラクタの説明:http://msdn.microsoft.com/ja-jp/library/3aadshsx(VS.80).aspx]]によると、
+
>Encoding.Default 以外を指定した場合、バイト順マーク がファイルに書き込まれます。
+

          
+
となっているので、Encoding.Default以外(例えばEncoding.UTF8)を指定するとBOMが書き込まれるように読み取れる。
+

          
+
#code(cs){{
+
var text = "日本語";
+

          
+
using {
+
  using {
+
    writer.Write(text);
+
  }
+
  Console.WriteLine(BitConverter.ToString(stream.ToArray()));
+
}
+

          
+
using {
+
  using {
+
    writer.Write(text);
+
  }
+
  Console.WriteLine(BitConverter.ToString(stream.ToArray()));
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
E6-97-A5-E6-9C-AC-E8-AA-9E
+
EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
+
}}
+

          
+
しかし実際には、次の例のようにEncoding.Default以外を指定しても、コンストラクタでencoderShouldEmitUTF8Identifierにfalseを指定したUTF8Encodingの場合はBOMが書き込まれない。
+

          
+
#code(cs){{
+
using {
+
  using {
+
    writer.Write(text);
+
  }
+
  Console.WriteLine(BitConverter.ToString(stream.ToArray()));
+
}
+

          
+
using {
+
  using {
+
    writer.Write(text);
+
  }
+
  Console.WriteLine(BitConverter.ToString(stream.ToArray()));
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
E6-97-A5-E6-9C-AC-E8-AA-9E
+
EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
+
}}
+

          
+
このようにBOMが書き込まれるかどうかは、UTF8Encoding(およびUnicodeEncoding、UTF32Encoding)のコンストラクタに指定する値によって決まる。 具体的には、StreamWriterがBOMを出力するかどうかは、[[Encoding.GetPreambleメソッド:http://msdn.microsoft.com/ja-jp/library/system.text.encoding.getpreamble(VS.80).aspx]]が返す値次第となる(と思われる)。
+

          
+
**BOMあり/なしの指定方法
+
StreamWriterがBOMを出力するようにするには、Encoding.GetPreambleメソッドがBOMを返すようなEncodingのインスタンスを渡す必要がある。
+

          
+
また、BinaryWriterなどはEncoding.GetPreambleメソッドの戻り値に関わらずBOMは書き込まれないので、例えばBinaryWriterでBOMありの出力を行いたい場合は、Writeメソッドを使ってEncoding.GetPreambleメソッドの戻り値を書き込む必要がある。
+

          
+
次のサンプルは、UTF8Encoding、UnicodeEncoding、UTF32Encodingの各コンストラクタにそれぞれ異なる値を指定して作成したインスタンスを使って、Encoding.GetPreambleメソッドが返す値と、BinaryWriter、StreamWriterに書き込まれる内容を比較したもの。
+

          
+
#code(cs){{
+
const bool bigEndian = true;
+
const bool littleEndian = false;
+
const bool bom = true;
+

          
+
var unicodeEncodings = new Dictionary<string, Encoding>() {
+
  {"UTF-8",                     new UTF8Encoding(!bom)},
+
  {"UTF-8},
+
  {"Encoding.UTF8",             Encoding.UTF8},
+
  {"UTF-16LE",                  new UnicodeEncoding(littleEndian, !bom)},
+
  {"UTF-16BE",                  new UnicodeEncoding(   bigEndian, !bom)},
+
  {"UTF-16LE},
+
  {"UTF-16BE},
+
  {"Encoding.Unicode",          Encoding.Unicode},
+
  {"Encoding.BigEndianUnicode", Encoding.BigEndianUnicode},
+
  {"UTF-32LE",                  new UTF32Encoding(littleEndian, !bom)},
+
  {"UTF-32BE",                  new UTF32Encoding(   bigEndian, !bom)},
+
  {"UTF-32LE},
+
  {"UTF-32BE},
+
  {"Encoding.UTF32",            Encoding.UTF32},
+
};
+

          
+
var text = "日本語";
+

          
+
foreach {
+
  var encoding = pair.Value;
+

          
+
  Console.WriteLine(pair.Key);
+
  Console.WriteLine("  BOM: {0}", BitConverter.ToString(encoding.GetPreamble()));
+

          
+
  using {
+
    using {
+
      writer.Write(text);
+
    }
+
    Console.WriteLine("  BinaryWriter: {0}", BitConverter.ToString(stream.ToArray()));
+
  }
+

          
+
  using {
+
    using {
+
      writer.Write(text);
+
    }
+
    Console.WriteLine("  StreamWriter: {0}", BitConverter.ToString(stream.ToArray()));
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
UTF-8
+
  BOM: 
+
  BinaryWriter: 09-E6-97-A5-E6-9C-AC-E8-AA-9E
+
  StreamWriter: E6-97-A5-E6-9C-AC-E8-AA-9E
+
UTF-8
+
  BOM: EF-BB-BF
+
  BinaryWriter: 09-E6-97-A5-E6-9C-AC-E8-AA-9E
+
  StreamWriter: EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
+
Encoding.UTF8
+
  BOM: EF-BB-BF
+
  BinaryWriter: 09-E6-97-A5-E6-9C-AC-E8-AA-9E
+
  StreamWriter: EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
+
UTF-16LE
+
  BOM: 
+
  BinaryWriter: 06-E5-65-2C-67-9E-8A
+
  StreamWriter: E5-65-2C-67-9E-8A
+
UTF-16BE
+
  BOM: 
+
  BinaryWriter: 06-65-E5-67-2C-8A-9E
+
  StreamWriter: 65-E5-67-2C-8A-9E
+
UTF-16LE
+
  BOM: FF-FE
+
  BinaryWriter: 06-E5-65-2C-67-9E-8A
+
  StreamWriter: FF-FE-E5-65-2C-67-9E-8A
+
UTF-16BE
+
  BOM: FE-FF
+
  BinaryWriter: 06-65-E5-67-2C-8A-9E
+
  StreamWriter: FE-FF-65-E5-67-2C-8A-9E
+
Encoding.Unicode
+
  BOM: FF-FE
+
  BinaryWriter: 06-E5-65-2C-67-9E-8A
+
  StreamWriter: FF-FE-E5-65-2C-67-9E-8A
+
Encoding.BigEndianUnicode
+
  BOM: FE-FF
+
  BinaryWriter: 06-65-E5-67-2C-8A-9E
+
  StreamWriter: FE-FF-65-E5-67-2C-8A-9E
+
UTF-32LE
+
  BOM: 
+
  BinaryWriter: 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
  StreamWriter: E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
UTF-32BE
+
  BOM: 
+
  BinaryWriter: 0C-00-00-65-E5-00-00-67-2C-00-00-8A-9E
+
  StreamWriter: 00-00-65-E5-00-00-67-2C-00-00-8A-9E
+
UTF-32LE
+
  BOM: FF-FE-00-00
+
  BinaryWriter: 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
  StreamWriter: FF-FE-00-00-E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
UTF-32BE
+
  BOM: 00-00-FE-FF
+
  BinaryWriter: 0C-00-00-65-E5-00-00-67-2C-00-00-8A-9E
+
  StreamWriter: 00-00-FE-FF-00-00-65-E5-00-00-67-2C-00-00-8A-9E
+
Encoding.UTF32
+
  BOM: FF-FE-00-00
+
  BinaryWriter: 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
  StreamWriter: FF-FE-00-00-E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
}}
+