はかせのラボ

私の頭の中を書いていく雑記ブログです

C# BOM地雷を踏まないために必要な知識をまとめてみる

あいさつ

どうも、はかせです。

以前こんな記事を投稿しました。
hakase0274.hatenablog.com

内容はC#でのファイルI/O基礎的なものです。

この記事の中で○○Readerやら○○Writerやらを
使っているのですが、
実は読み書きするファイルによっては
「文字化け」が起こります
(通称BOM地雷)

この文字化け問題は「BOM」というものが
関わってきます。

今回は上記の記事から一歩踏み込んで
この「BOM」について書きます。

BOMとは

Byte Order Mark
の頭文字を取って
BOMです。

じゃこのBOMってのは何なのかって言うと
ファイル先頭数バイトの領域に書き込まれる
見えない識別子です。

その昔まだUnicodeが主流文字コードで無く
数多の文字コードが混在していた時代、
一体このファイルが何の文字コードエンコーディングされているのか
判別する必要がありました。

ASCIIなんかは一文字に使われるバイト数が
決め打ちだったので問題無かったのですが、
Unicodeは一文字に数バイト使います。

なのでこのBOMが無いと正常に認識できなかったわけです。

BOMが何故文字化けを

ありていに言えば
その環境がBOM付Unicodeに対応してないからです。

対応してなければよくわからない
数バイトのデータがあるわけで
ファイルがバグッてると認識されてもおかしくないわけです。

結果正しく表示されず、
文字化けが起こるわけですねえ。

昔であれば必要であったBOMですが、
主流となった今では、
邪魔な存在になってしまっているわけですね。
いやはや悲しい話です。

BOMの有無をどうやって切り替える

さてここからはタグのC#の回収です。

まずStreamReaderを使って読み込んだ場合
BOMは除外されます。
なので読み込みはStreamReader使ってる場合
BOMのことは考えなくていいかと思います。

BinaryReaderを使ってる場合はBOM入ってくるので注意です。
といっても先頭の数バイト(何バイトかは文字コードからググってください)
を無視すればいいだけなので
そこまでむずかしくないです。

ということで○○Reader系は終わりです。

次にWriter系。
こいつらはコンストラクタの第二引数に渡す
Encodingの値によって切り替えます。
具体的にはこう

new StreamWriter(stream);//BOM無し
new StreamWriter(stream,Encoding.UTF8);//BOM有り
new StreamWriter(stream,new UTF8Encoding(true));//BOM有り
new StreamWriter(stream,new UTF8Encoding(false));//BOM無し

引数に何も渡さなければデフォルトUTF8の
BOM無でやってくれるそうです。

Encoding.○○はBOM付いちゃうらしいです。

newで作った場合有無は
コンストラクタのbool値で切り分けるそうですよ。

BOMが有用な場面

さてここまでBOMは死すべし慈悲はないみたいな
口調で話を進めてきましたが、
BOMが生きるというかBOMが必要な場面が少なくとも一つあります。

それはOfficeとの連携です。
おそらく開発の場合だとExcelがメインになると思いますが、
あいつらはデフォルトShift_JISです。
もちろんUnicodeにも対応してますが、
BOMが付いてないとUnicodeと認識してくれません

IEといいMicroSoftのソフトは色々めんどくさいですね。
まぁWindowsユーザーなんで
あまり文句は言いたくないんですが。
(C#MicroSoftだったわ)

あとがき

今回はBOMについて書いてみました。
基本なんも指定しなければBOM無やってくれます。

私が冒頭に紹介した記事のサンプルコードでBOM付で出してたのは
私がしょっちゅうExcelと連携する関係上
BOM付で使うことが多くその中からブッコ抜いてきたからですね。

なのでその辺と連携したければBOM付で
それ以外の場合はBOM無で扱うのがいいと思います。

今回の記事が良ければスターやコメント等よろしくお願いします。
それでは今回はこの辺でノシ