「CSVファイルをExcelで開いたら先頭に謎の文字が表示された」「PHPスクリプトの冒頭に余計なバイトが混入してエラーになった」——これらのトラブルの多くはUTF-8 BOMが原因です。
BOMはファイルの文字コードを識別するためのマークですが、使う場面を誤ると深刻な問題を引き起こします。この記事では、UTF-8 BOMの基本概念・役割・デメリット・付与方法・使い分けの判断基準まで、開発者からビジネスユーザーまでわかりやすく解説します。
UTF-8 BOMとは

BOM(Byte Order Mark)の基本概念
BOMとは、テキストファイルの先頭に付加される特殊なバイト列で、「このファイルはどの文字コードで書かれているか」をアプリケーションに伝えるためのマークです。日本語に直訳すると「バイト順序マーク」となります。
UTF-8のBOMは以下の3バイトで構成されています。
0xEF 0xBB 0xBF
この3バイトはファイルの最初に追加され、人間には見えませんが、テキストエディタやプログラムがファイルを読み込む際に文字コードの識別に使われます。
UTF-8でBOMが使われる意味
BOMは本来、バイト順序(エンディアン)を識別するために設計されました。UTF-16やUTF-32では、1文字を複数バイトで表現するため、バイトをビッグエンディアン(上位バイトが先)で並べるかリトルエンディアン(下位バイトが先)で並べるかを明示する必要があります。
UTF-8は1バイト単位でエンコードするため、バイト順序の問題は発生しません。したがって、UTF-8においてBOMは「文字コードがUTF-8であることを宣言する」ための識別子として使われています。技術的には不要ですが、一部の環境との互換性のために使われます。
UTF-8と他の文字コード(UTF-16、UTF-32)の違い
| 文字コード | BOMのバイト列 | BOMの必要性 |
|---|---|---|
| UTF-8 | EF BB BF |
任意(なしが標準) |
| UTF-16 BE | FE FF |
推奨(バイト順序の明示) |
| UTF-16 LE | FF FE |
推奨(バイト順序の明示) |
| UTF-32 BE | 00 00 FE FF |
推奨(バイト順序の明示) |
| UTF-32 LE | FF FE 00 00 |
推奨(バイト順序の明示) |
IETFのRFC 3629では、UTF-8においてBOMを付与しないことを推奨しています。UTF-8はバイト順序の問題がないため、BOMなしがインターネット標準における推奨形式です。
UTF-8 BOMの役割とメリット

ファイルの文字コードを明示できる
BOMを付けることで、ファイルの文字コードがUTF-8であることをアプリケーションが確実に識別できます。文字コードの自動判別機能が弱い古いアプリケーションや環境では、BOMの有無がファイルの正しい読み込みを左右する場合があります。
特にWindowsの旧来のアプリケーションは、BOMなしUTF-8ファイルをShift-JISや別のエンコードと誤認識することがありました。BOMを付けることでこの誤認識を防げます。
エディタやアプリケーションでの文字化け防止
以下のようなシーンでBOM付きUTF-8が文字化け防止に役立ちます。
- ExcelでのCSVファイル読み込み: Microsoft ExcelはBOM付きUTF-8のCSVを文字コード指定なしで正しく開ける。BOMなしだとShift-JISと誤認識して日本語が文字化けする
- 古いWindowsアプリケーション: BOMを文字コード識別の手がかりとして使っているアプリとの互換性が確保される
- テキストエディタ間のファイル共有: BOMがあることでエディタが文字コードを明確に認識できる
特定環境での互換性確保
Microsoft製品(Excel・Visual Studio・SharePointなど)はBOM付きUTF-8との親和性が高く、Windows環境でのファイル共有や業務システムとの連携ではBOM付きの方が安定する場合があります。UTF-8 BOMとExcel・Windows環境との互換性についてはこちらの記事も参考になります。
UTF-8 BOMのデメリット・注意点

BOMがあることで発生する文字化け
BOMの3バイト(EF BB BF)をそのまま文字として表示してしまうアプリケーションでは、ファイルの先頭に「」や「」のような見慣れない文字が表示されます。これが文字化けの一形態です。
特にWebブラウザでHTMLファイルを開いたとき、BOMが正しく処理されない環境ではページの先頭に余計な空白や記号が表示されることがあります。
スクリプトやプログラムで予期せぬ影響が出るケース
BOM付きUTF-8は、多くのプログラミング言語・スクリプト環境・Webサーバーで問題を引き起こします。代表的な影響を以下に示します。
| 環境・言語 | BOMによる問題 |
|---|---|
| PHPスクリプト | BOMがHTTPレスポンスヘッダーの前に出力されてしまい、header()関数が機能しなくなる |
| シェルスクリプト(Bash) | 1行目の#!/bin/bashの前にBOMが入ることでインタープリタが認識されずエラーになる |
| JSONファイル | JSON仕様(RFC 8259)でBOMは禁止されており、パースエラーになる場合がある |
| Python | Python 3ではUTF-8 BOMをutf-8-sigとして扱うが、通常のutf-8として読み込むとBOMが先頭文字として残る |
| CSVパーサー | 最初の列名にBOM文字が含まれて"列名"ではなく"列名"として認識される |
不要な場合はBOMなしで保存する方が安全
Web開発・サーバーサイドスクリプト・Linux環境でのファイル操作においては、BOMなしUTF-8が事実上の標準です。UTF-8はバイト列の構造自体に識別できる特徴があるため、BOMがなくても文字コードの判別は可能です。迷った場合はBOMなしを選ぶのが安全です。
UTF-8 BOMの付与方法

エディタでBOM付きUTF-8として保存する方法
主要なテキストエディタでのBOM付き保存方法を解説します。
メモ帳(Windows 10/11):
- ファイル → 名前を付けて保存
- 「文字コード」ドロップダウンから「UTF-8(BOM付き)」を選択
- 保存をクリック
確認方法: Windows 10 1903以降、メモ帳の文字コードリストに「UTF-8」と「UTF-8(BOM付き)」が分離して表示されるようになりました。
サクラエディタ:
- ファイル → 名前を付けて保存
- 「文字コードセット」で「UTF-8」を選択
- 「BOMの有無」チェックボックスを有効にする
Visual StudioやVSCodeでのBOM設定方法
Visual Studio Code(VSCode):
VSCodeの画面右下に表示されている文字コード表示(例:「UTF-8」)をクリックします。
- 「エンコード付きで保存」をクリック
- 検索欄に「bom」と入力
- 「UTF-8 with BOM」を選択
またはsettings.jsonで特定のファイルタイプにBOMを自動付与する設定も可能です。
// settings.json
{
"files.encoding": "utf8bom" // デフォルトをBOM付きに設定
}
Visual Studio(2019/2022):
ファイル → 名前を付けて保存 → 保存ボタンの右の▼をクリック → 「エンコード付きで保存」 → 「Unicode(BOM付きUTF-8)」を選択
VSCodeでのBOM設定の詳細な手順はこちらの記事でも確認できます。
LinuxやコマンドラインでBOMを付与する方法
既存ファイルにBOMを追加する(sed使用):
# sedを使ってBOMを先頭に追加
printf '\xEF\xBB\xBF' | cat - file.txt > file_bom.txt
pythonを使ってBOMなし→BOM付きに変換:
# Python 3でBOM付きUTF-8に変換
python3 -c "
with open('input.txt', 'r', encoding='utf-8') as f:
content = f.read()
with open('output.txt', 'w', encoding='utf-8-sig') as f:
f.write(content)
print('BOM付きUTF-8に変換完了')
"
BOMの有無をコマンドラインで確認する:
# hexdumpでファイル先頭のバイトを確認
hexdump -C file.txt | head -1
# BOM付きの場合の出力例
# 00000000 ef bb bf e3 81 82 e3 81 84 e3 81 86 0a |...あいう.|
# fileコマンドでの確認(UTF-8 with BOMと表示される)
file file.txt
BOMを除去する方法:
# sedを使ってBOMを除去
sed -i '1s/^\xEF\xBB\xBF//' file.txt
# Python 3でBOMありをBOMなしに変換
python3 -c "
with open('input.txt', 'r', encoding='utf-8-sig') as f:
content = f.read()
with open('output.txt', 'w', encoding='utf-8') as f:
f.write(content)
"
BOM付きファイルとBOMなしファイルの違い
見た目では変わらないがバイナリ上の違い
テキストエディタで見た目には同じように見えますが、バイナリレベルでは先頭3バイトの有無という明確な差があります。
# 同じ「こんにちは」というテキストのバイナリ比較
# BOMなしUTF-8
e3 81 93 e3 82 93 e3 81 ab e3 81 a1 e3 81 af
# BOM付きUTF-8
ef bb bf e3 81 93 e3 82 93 e3 81 ab e3 81 a1 e3 81 af
↑ BOMの3バイト(EF BB BF)が先頭に追加されている
ファイルサイズはBOM付きの方が常に3バイト大きくなります。1つのファイルでは微差ですが、大量のファイルを扱うシステムでは考慮が必要な場合があります。
プログラムやスクリプトでの読み込み挙動の違い
BOMの有無でプログラムの挙動が変わる代表的なケースです。文字コードとBOMがプログラムに与える影響の詳細な解説はこちらの記事も参考になります。
# Python: BOMありファイルとBOMなしファイルの読み込み比較
# BOMなしUTF-8を通常のutf-8で読み込む(正常)
with open('nobom.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(repr(content[:5])) # 出力: 'こんにちは'
# BOM付きUTF-8を通常のutf-8で読み込む(BOM文字が残る)
with open('bom.txt', 'r', encoding='utf-8') as f:
content = f.read()
print(repr(content[:5])) # 出力: '\ufeffこんに' ← BOMが先頭文字として残る
# BOM付きUTF-8をutf-8-sigで読み込む(BOMを自動除去)
with open('bom.txt', 'r', encoding='utf-8-sig') as f:
content = f.read()
print(repr(content[:5])) # 出力: 'こんにちは' ← 正常
どの場面でBOMあり・なしを選ぶべきか
| 場面・用途 | 推奨 | 理由 |
|---|---|---|
| Webサイト(HTML/CSS/JS) | BOMなし | ブラウザやWebサーバーでBOMが問題になる場合がある |
| PHPスクリプト | BOMなし | BOMがHTTP出力前に送信されてheader()が失敗する |
| シェルスクリプト | BOMなし | shebangが認識されずスクリプトが実行できない |
| JSONファイル | BOMなし | RFC 8259でBOM禁止 |
| ExcelへのCSV読み込み | BOMあり | BOMなしだとShift-JISと誤認識して日本語が文字化けする |
| Windowsのメモ帳で開くファイル | BOMあり | BOMなしUTF-8をShift-JISと誤認識する環境がある |
| Visual Studioでの開発 | プロジェクトに依存 | プロジェクト設定に合わせる |
UTF-8 BOMを扱うときの注意点
既存ファイルを編集するときのBOM維持
既存のBOM付きファイルをエディタで開いて保存する際、エディタによってはBOMが自動的に除去される場合があります。チームで開発している場合、BOMの有無が作業者によって変わってしまうと、予期しないバグや文字化けの原因になります。
プロジェクトのコーディング規約でBOMの有無を統一し、チーム全員がその設定に従うことが重要です。
VSCodeで既存ファイルのBOM設定を確認する方法:
- VSCodeの右下ステータスバーの文字コード表示を確認する
- 「UTF-8 with BOM」と表示されていればBOM付き、「UTF-8」のみならBOMなし
GitやバージョンNO管理でのBOMの影響
GitはBOMの3バイトも通常のファイル変更として検出します。BOMの有無が変わるとdiffに意図しない差分が生じ、コードレビューの妨げになります。GitとBOMの関係について詳しくはこちらの記事でも解説されています。
# .gitattributesでBOMなしUTF-8を強制する設定例
# *.php text eol=lf
# *.js text eol=lf
# BOM付きファイルが混入していないか確認するコマンド
grep -r $'\xEF\xBB\xBF' --include="*.php" .
grep -r $'\xEF\xBB\xBF' --include="*.js" .
Web開発プロジェクトでは.editorconfigファイルでエディタの文字コードを統一する方法も有効です。
# .editorconfig の設定例
[*]
charset = utf-8 # BOMなしUTF-8を指定
[*.csv]
charset = utf-8-bom # CSVのみBOM付きに設定
他の文字コードとの変換時の注意
Shift-JISやEUC-JPなどのファイルをUTF-8に変換する際、変換ツールによってBOMが付与されるかどうかが異なります。
# iconvでShift-JISをUTF-8(BOMなし)に変換
iconv -f SHIFT-JIS -t UTF-8 input.txt > output.txt
# nkfでShift-JISをUTF-8に変換
nkf -w input.txt > output.txt # BOMなし
nkf -w8 input.txt > output.txt # BOM付き(-w8オプション)
# 変換後にBOMの有無を確認
hexdump -C output.txt | head -1
Tips: 変換前後でファイルのバイト数だけでなく、hexdumpでBOMの有無も確認することで、予期しないBOMの混入を防げます。
まとめ
UTF-8 BOMは文字コード識別用のマーク
UTF-8 BOMはファイル先頭の3バイト(EF BB BF)で構成される文字コード識別用のマークです。UTF-16・UTF-32とは異なり、UTF-8においてバイト順序の問題はないため、BOMは技術的には不要ですが、一部の環境との互換性確保のために使われます。
互換性や文字化け防止に役立つが、不要な場合は避ける
- ExcelでのCSV読み込みやWindowsアプリとの互換性ではBOM付きが有効
- PHP・シェルスクリプト・JSONなどではBOMが深刻な動作不具合を引き起こす
- Web開発・Linux環境・Git管理下のファイルはBOMなしが標準
- RFC 3629でUTF-8にBOMを付けないことが推奨されている
- 迷ったらBOMなしUTF-8を選ぶのが安全
エディタや環境に応じてBOM付き・なしを使い分けることが重要
BOMの有無は用途と環境によって最適解が異なります。チームやプロジェクトでコーディング規約としてBOMの扱いを統一し、.editorconfigや.gitattributesで設定を管理することで、BOM起因のトラブルを未然に防ぐことができます。「何も考えずにBOMを付ける」のではなく、「なぜBOMが必要か」を理解した上で適切に使い分けることが、文字コードトラブルを防ぐ最善策です。

