コンテンツにスキップ

bom付き

概要

「bom付き」とは、テキストファイルの先頭にByte Order Mark (BOM) と呼ばれる特殊なバイト列が付与されている状態を指します。BOMは、主にUTF-8、UTF-16、UTF-32といったUnicodeエンコーディングのテキストファイルにおいて、そのファイルがどのエンコーディングで記述され、かつ多バイト文字のバイト順(ビッグエンディアンかリトルエンディアンか)がどうなっているかを明示的に示すために使用されます。

このバイト列は、ファイルの読み込み時にテキストエディタやプログラムがエンコーディングを自動的に識別するためのヒントとなります。特にUTF-16やUTF-32ではバイト順の識別が重要ですが、UTF-8においても、一部の環境(特にWindows)でエンコーディング識別のために用いられることがあります。

BOMは通常、表示されない不可視文字として扱われますが、その有無がアプリケーションやプログラミング言語の動作に影響を与えることがあるため、IT分野ではその存在がしばしば議論の対象となります。

注目される背景

コンピュータシステムが多様な言語を扱うようになるにつれ、テキストファイルのエンコーディング問題は常に開発者を悩ませてきました。ASCIIのようなシングルバイト文字セットが主流だった時代はシンプルでしたが、Unicodeの登場と普及により、マルチバイト文字セット(UTF-8, UTF-16など)が標準となり、異なるシステム間でファイルを交換する際のエンコーディングの判別がより複雑になりました。

BOMは、ファイルのエンコーディング情報を明示的に埋め込むことで、このような判別を容易にする手段として注目されました。特にWindows環境では、メモ帳などの多くのアプリケーションがBOMの有無によってUTF-8ファイルを認識するため、BOM付きUTF-8が広く利用されています。しかし、Unix/Linux環境や多くのプログラミング言語のパーサーでは、BOMがないUTF-8が標準的であるため、BOM付きファイルが原因で構文エラーや予期せぬ動作を引き起こすことがあり、これがBOMがIT分野で頻繁に議論される背景となっています。

核心的な考え方

BOMの核心的な考え方は、「自己記述型メタデータ」の原則に基づいています。つまり、テキストファイル自体がその内容(この場合はエンコーディングとバイト順)を解釈するための情報を、ファイルの先頭という最もアクセスしやすい位置に含めることで、読み込み側のシステムやアプリケーションが外部からの追加情報なしにファイルを正しく処理できるようにすることです。これは、異なる環境間での相互運用性(Interoperability)を高めるための試みと言えます。

仕組み・詳細

BOMは、Unicodeの「U+FEFF」(Zero Width No-Break Space)という特殊な文字を、特定のエンコーディングでバイト列として表現したものです。ファイルの先頭にこのバイト列が存在することで、読み込み側のプログラムはそのエンコーディングを推測できます。

各エンコーディングにおけるBOMのバイト列

エンコーディング BOMバイト列 (16進数) バイト数 備考
UTF-8 EF BB BF 3 バイト順の概念はない。エンコーディング識別子として使用。IANAおよびUnicode Consortiumは非推奨。
UTF-16 Big Endian FE FF 2 ビッグエンディアンを示す。
UTF-16 Little Endian FF FE 2 リトルエンディアンを示す。
UTF-32 Big Endian 00 00 FE FF 4 ビッグエンディアンを示す。
UTF-32 Little Endian FF FE 00 00 4 リトルエンディアンを示す。

UTF-8におけるBOMの役割

UTF-8は可変長エンコーディングであり、バイト順の概念がないため、技術的にはBOMは不要です。しかし、一部のアプリケーション(特にWindowsのメモ帳など)では、BOMの有無でUTF-8ファイルを区別します。BOMがないUTF-8ファイルは、システムのデフォルトエンコーディング(ANSI)として誤認識されることがあるため、Windows環境ではBOM付きUTF-8が用いられることがあります。

UTF-16およびUTF-32におけるBOMの役割

UTF-16やUTF-32では、1文字が2バイトまたは4バイトで表現されます。これらのエンコーディングでは、メモリ上でのバイト順(ビッグエンディアンかリトルエンディアンか)を識別するためにBOMが非常に重要です。例えば、UTF-16BEの場合 FE FF となるバイト列が、UTF-16LEの場合 FF FE となることで、正しいバイト順で文字を読み込むことができます。

関連手法・技術との比較

エンコーディング情報を伝える方法はBOM以外にもいくつか存在します。

特徴 BOM MIME Type (HTTPヘッダ) XML宣言 HTMLの<meta charset>
位置 ファイルの先頭 HTTPレスポンスヘッダ XMLドキュメントの先頭 HTMLドキュメントの<head>
適用範囲 テキストファイル全般 HTTPで転送されるリソース XMLドキュメント HTMLドキュメント
検出方法 バイト列による自己記述 ヘッダ情報による伝達 XML構文による記述 HTML構文による記述
ファイル内容への影響 バイト列が追加される なし 構文要素が追加される 構文要素が追加される
主な目的 エンコーディングとバイト順の識別 コンテンツタイプとエンコーディングの伝達 XMLのバージョンとエンコーディングの伝達 HTMLドキュメントのエンコーディング指定
主な使用環境 ファイルシステム、Windowsアプリ Webサーバーとクライアント XMLパーサー Webブラウザ

メリット

  • エンコーディングの自動判別: ファイルのエンコーディングを明示的に示すため、多くのテキストエディタやアプリケーションが自動的に正しいエンコーディングでファイルを開くことができます。特に、他のメタデータがない場合に有効です。
  • バイト順の明確化: UTF-16やUTF-32のような多バイトエンコーディングにおいて、Big EndianとLittle Endianのバイト順を確実に識別できるため、異なるシステム間での互換性が向上します。
  • Windowsアプリケーションとの互換性: Windows環境のメモ帳などのアプリケーションは、BOM付きUTF-8ファイルを正しくUTF-8として認識するため、文字化けを防ぐことができます。

課題・注意点

  • 互換性の問題: 多くのUnix/Linux系ツールやプログラミング言語(PHP, Python, Ruby, Perlなど)のパーサーは、BOMをファイル内容の一部(不可視文字)と見なしてしまい、構文エラーや警告の原因となることがあります。
    • 例: PHPスクリプトの先頭にBOMがあると、headers already sent エラーが発生することがある。
    • 例: Pythonでは、BOMが原因で SyntaxError: invalid character が発生することがある。
  • ファイル結合時の問題: BOM付きファイルを複数結合すると、結合されたファイルの中間にもBOMが出現し、文字化けやプログラムの誤動作の原因となる可能性があります。
  • UTF-8での不要性: UTF-8エンコーディングはバイト順の概念がないため、BOMは技術的には不要であり、IETF (RFC 3629) やUnicode ConsortiumはUTF-8でBOMを使用しないことを推奨しています。
  • 視認性の低さ: 通常のエディタではBOMは表示されないため、BOMの有無を意識せずにファイルを編集し、問題を引き起こすことがあります。
  • 微量なファイルサイズ増加: BOMは数バイト程度の情報ですが、極めて多数のファイルを扱う場合、総ファイルサイズに影響を与える可能性はゼロではありません。

代表的なツール / 実装例

  • テキストエディタ:
    • メモ帳 (Windows): デフォルトでUTF-8形式で保存する場合、BOMが付与されます。BOMなしでUTF-8を保存する機能はありません。
    • Notepad++: ファイルの保存時に、「UTF-8 BOMなし」や「UTF-8」を選択してBOMの有無を明示的に指定できます。
    • Visual Studio Code: デフォルトではBOMなしUTF-8で保存されますが、ステータスバーのエンコーディング表示から「BOMで保存」や「BOMなしで保存」を選択して変更できます。
    • サクラエディタ: 保存時のエンコーディング選択ダイアログで、BOMの有無を指定できます。
  • プログラミング言語・ツール:
    • PHP: PHPスクリプトファイルにBOMがあると、PHPエンジンがそれを出力と見なし、header() 関数を呼び出す前に出力があるためエラーとなることが多いです。
    • Python: Python 3では、ファイルを開く際に open('file.py', encoding='utf-8-sig') のように utf-8-sig エンコーディングを指定することでBOMを自動的にスキップして読み込むことができます。
    • Git: GitはBOMの有無をファイルの差分として認識します。そのため、BOMの追加や削除はバージョン管理上の変更点として扱われます。
    • iconv (Linuxコマンド): コマンドラインでBOMを削除/追加する際に利用できます。
      # BOM付きUTF-8ファイルをBOMなしUTF-8に変換
      iconv -f UTF-8 -t UTF-8 file_with_bom.txt > file_without_bom.txt
      # BOMなしUTF-8ファイルをBOM付きUTF-8に変換 (少し複雑な記述が必要)
      # iconv -f UTF-8 -t UTF-8//BOM file_without_bom.txt > file_with_bom.txt
      # または、echo -e "\xEF\xBB\xBF" | cat - file_without_bom.txt > file_with_bom.txt
      

参考URL

  • Byte Order Mark - Wikipedia: https://ja.wikipedia.org/wiki/Byte_Order_Mark
  • UTF-8 の BOM (Byte Order Mark) について - Qiita: https://qiita.com/tatsurou313/items/c97b2f4233c07f2c8d20
  • PHPとBOMの弊害 - Qiita: https://qiita.com/t_fujiwara/items/1b7327e5f10b7f6c8d76
  • Pythonの文字コード、Unicode、UTF-8、BOM - Qiita: https://qiita.com/hi-waka/items/9ce5d10d18b2c28659b8
  • UTF-8 BOM は本当にいらないのか? - Microsoft Docs の情報を見て考えた - Zenn: https://zenn.dev/tatsurou313/articles/e53f19e48f1f72