はじめに
データ連携やシステム開発において、以下のようなトラブルに直面したことはないでしょうか。
「CSVをExcelで開いたら盛大に文字化けした」
「連携先から『先頭に謎の3バイトゴミが入っていてパースエラーになる』とクレームが飛んできた」
これらはBOMの有無に起因するトラブルです。UTF-8では不要論も根強い一方、業務システムでは「BOMあり/なし」の要件が混在する実情があります。
文字コード変換では一文字一文字を変換していきます。例えばシフトJISからUTF-8に変換する場合、「あ」を意味する「82A0」があると、UTF-8の「あ」である「E38182」に変換します。BOMは、それとは別個に実装する必要があります。
「どうやって実装しよう?」と頭を悩ませるところですが、データ変換ツールDTR 1 を使えば、難しいことを考えなくても、簡単な設定だけでBOMの入出力が可能になります。この記事では、BOMの基礎知識やメリット・デメリットを整理した上で、DTRを使ってBOMあり/なしUTF-8を出力してみます。
BOMとは
BOM: Byte Order Markは、テキストファイルの先頭に置かれる数バイトの特殊なデータです。そのファイルの文字コードやバイトの並び順(エンディアン)を識別するために使われます。
以下が代表的なBOMです。
| 文字コード | BOM 16進値 |
|---|---|
| UTF-8 | EF BB BF |
| UTF-16LE | FF FE |
| UTF-16BE | FE FF |
UTF-16には「上位バイトと下位バイトのどちらが先か」というエンディアンの区別があります。例えば「あ」はUnicodeではU+3042です。UTF-16のビッグエンディアンではそのまま16進値で30 42となります。リトルエンディアンでは42 30と逆になります。これに対してUTF-8は文字によってバイト数が変動するものの、処理の最小単位は1バイトであるため、エンディアンの区別はありません。
BOMを付すことは義務ではありません。送り手と受け手の間で仕様の合意があればBOMは不要です。特にUTF-8はエンディアンの区別がないため、BOMは必須でも推奨でもありません。
BOMのメリットはエンコーディングを自動判別しやすいことです。逆にデメリットは、パーサーのエラーやレイアウト崩れを引き起こす危険があることです。例えばBOMありUTF-8のファイルを読み込もうとしたところ、プログラムで先頭に想定外のバイトシーケンス(EF BB BF)が混入してエラーになることがあります。
一方でBOMありしかサポートしていないシステムもあります。例えばMicrosoft ExcelでCSVファイルをダブルクリックして開く場合、BOMありUTF-8で保存されたCSVファイルは正常に表示されますが、BOMなしUTF-8のCSVファイルは文字化けします。このため、BOM出力ファイルの連携が要件になることもあります。
この画像はUTF-8のBOMの有無を解説する図です。自作キャラクター「エフティーアドニャン」を用いて生成AIで作成しました。エフティーアドニャンはファイルの転送を見守るファイルの妖精という設定の架空のキャラクターです。
DTRのBOM入出力
データ変換ツールDTRはBOMありとBOMなしの両方に対応しています。
入力ファイルのBOM有無は環境設定ファイル(dtrconf)の「ibom」で指定します。
| 指定 | 動作 |
|---|---|
| 指定省略時 | BOMなしのテキスト入力 |
| ibom off | BOMなしのテキスト入力 |
| ibom on | BOMありのテキスト入力 |
出力ファイルのBOM有無は環境設定ファイルの「obom」で指定します。
| 指定 | 動作 |
|---|---|
| 指定省略時 | BOMなしのテキスト出力 |
| obom off | BOMなしのテキスト出力 |
| obom on | BOMありのテキスト出力 |
環境設定ファイル
環境設定ファイルの指定方法は、以下の3種類があります。
- 任意のファイルを作成してオプション「-e」で指定します。コマンドの実行単位でBOMの有無を制御できます。コマンドごとに設定を切り替えたい場合に適しています。
- カレントディレクトリにdtrconfの名前で作成します。同じディレクトリで実行するコマンドに対して、共通の設定を適用できます。特定の業務やプロジェクトで共通の設定を利用する場合に適しています。
- DTRの導入ディレクトリ内にdtrconfの名前で作成します。OS全体で共通の既定設定を適用したい場合に適しています。特に指定がない場合の標準設定として利用できます。
複数の環境設定ファイルが存在する場合は、上記の順に優先されます。つまり、1. コマンドオプション「-e」 > 2. カレントディレクトリ > 3. 導入ディレクトリの順です。
検証
それでは実際にDTRを使って検証します。今回はBOM出力に焦点を当て、BOMなしUTF-8とBOMありUTF-8のCSVファイルを出力します。
以下の環境で検証しました。
- OS:Windows 11 Enterprise
- ソフトウェア:DTRII 5R22V, Microsoft Excel
DTRIIはDTRのWindows版の商品名です。
入力ファイルはエフティーアドニャンを歌ったラップです。
1行42バイトのシフトJISのテキストファイルです。
最初の2バイトが行番号、残り40バイトがラップ本文です。
01エフティーアドニャン 繋ぐライン
02笑っていれば いつもファイン
03進捗100% 完璧なプラン
04語尾につけるぜ 栄光の「ニャン!」
05冷たいサーバー 温めるスマイル
06愛らしさ運ぶ 何マイル?
07エラーも弾くぜ キャットウォーク
08不具合お見通し サイレントトーク
09フォルダの奥からジャンプでイン
10転送チューニング 完全にWin
11ちらし寿司ビジョンでちょいと混乱
12それでも最後はやり切る本番
13「まだ99%ニャン…」って嘆願
14次の瞬間 完了の快感
15蝋梅 香ると状態良好
16パケット回避は秒速行動
17バドミントン仕込みの軽快機動
18ドジでもなぜか結果は上等
BOMなしUTF-8出力
これを以下のDTRコマンドでBOMなしUTF-8のCSVファイルに変換します。
C:\dtr\dtrnt '{ c2 m60,m40 }' -A -S エフティーアドニャンrap.txt -V -PQ 3 エフティーアドニャンrap-utf8.csv
DTRコマンドはコマンドプロンプトから実行しました。他のDTRコマンド実行箇所も同じです。
「C:\dtr」はDTRのデフォルトの導入ディレクトリです。
「c2」は入力の半角文字2バイトをそのまま出力します。
「m60,m40」は入力の全角・半角混合項目40バイトを60バイトに変換して出力します。シフトJISからUTF-8への変換では、シフトJISに収録されている全角文字は1文字2バイトに対し、UTF-8は1文字3バイトになるため、全て全角文字の場合の最大バイト数は入力の1.5倍になります。
半角カナはシフトJISでは1バイト、UTF-8では3バイトになるため、半角カナが混ざった入力では60バイトでは足りなくなるケースが生じます。半角カナを含む場合は最大3倍になります。
オプションの意味は以下の通りです。
| オプション | 意味 |
|---|---|
| -A | ASCII |
| -S | シフトJIS |
| -V | CSVファイル |
| -PQ 3 | UTF-8 |
BOMなし出力がデフォルトのため、環境設定ファイルを指定しません。
DTRコマンドを実行すると、BOMなしUTF-8のCSVファイルが生成されます。
01,エフティーアドニャン 繋ぐライン
02,笑っていれば いつもファイン
03,進捗100% 完璧なプラン
04,語尾につけるぜ 栄光の「ニャン!」
05,冷たいサーバー 温めるスマイル
06,愛らしさ運ぶ 何マイル?
07,エラーも弾くぜ キャットウォーク
08,不具合お見通し サイレントトーク
09,フォルダの奥からジャンプでイン
10,転送チューニング 完全にWin
11,ちらし寿司ビジョンでちょいと混乱
12,それでも最後はやり切る本番
13,「まだ99%ニャン…」って嘆願
14,次の瞬間 完了の快感
15,蝋梅 香ると状態良好
16,パケット回避は秒速行動
17,バドミントン仕込みの軽快機動
18,ドジでもなぜか結果は上等
以下のログも出力されます。
BIPROGY データ変換プログラム
データ変換終了(5R22V)
入力ファイル名--エフティーアドニャンrap.txt
入力レコード数: 18
出力ファイル名--エフティーアドニャンrap-utf8.csv
出力レコード数: 18
出力CSVファイルをダブルクリックしてExcelで開くと文字化けします。

ExcelのA列の値が1行目から9行目は左詰め、10行目以降は右詰めで表示されています。これはExcelの型の自動判定の結果です。「01」など頭に0が付く値は文字列、「10」以降は数値として判断され、それらの型の表示形式で表示されます。
DTRIIには16進ダンプのビューア「Xダンプ」が同梱されており、任意のファイルの16進値を確認することができます。XダンプはWindowsスタートメニューのDTRIIのフォルダから選択します。XダンプはGUIで16進値を確認できるだけでなく、ファイルに16進ダンプを出力することもできます。出力結果は以下になります。
Adr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
---------- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000000000 30 31 2C E3 82 A8 E3 83 95 E3 83 86 E3 82 A3 E3 : 01,繧ィ繝輔ユ繧」・
0000000010 83 BC E3 82 A2 E3 83 89 E3 83 8B E3 83 A3 E3 83 : ・繧「繝峨ル繝」繝
0000000020 B3 20 E7 B9 8B E3 81 90 E3 83 A9 E3 82 A4 E3 83 : ウ 郢九$繝ゥ繧、繝
(以下略)
最初の3バイト「30 31 2C」は「01,」です。
次の3バイト「E3 82 A8」はカタカナの「エ」です。
その次の3バイト「E3 83 95」はカタカナの「フ」です。
BOMなしのUTF-8であることが分かります。
右側のテキスト列はXダンプがシフトJISで表示するための見かけ上の文字化けであり、バイト列自体は正常なUTF-8です。
BOMありUTF-8出力
続いてBOMありUTF-8を出力します。
まず環境設定ファイルを作成します。以下のテキストファイルを作成して保存します。
obom on
環境設定ファイルを指定した以下のDTRコマンドを実行します。
C:\dtr\dtrnt '{ c2 m60,m40 }' -A -S エフティーアドニャンrap.txt -V -PQ 3 エフティーアドニャンrap-utf8-BOM.csv -e dtrconf
出力CSVファイルをダブルクリックしてExcelで開くと文字化けせずに表示されます。

出力ファイルを「Xダンプ」で16進ダンプにします。
Adr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
---------- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000000000 EF BB BF 30 31 2C E3 82 A8 E3 83 95 E3 83 86 E3 : ・ソ01,繧ィ繝輔ユ・
0000000010 82 A3 E3 83 BC E3 82 A2 E3 83 89 E3 83 8B E3 83 : ぅ繝シ繧「繝峨ル繝
0000000020 A3 E3 83 B3 20 E7 B9 8B E3 81 90 E3 83 A9 E3 82 : 」繝ウ 郢九$繝ゥ繧
(以下略)
先頭にBOM「EF BB BF」があり、BOMありUTF-8になっていることが確認できました。
おわりに
「たかが数バイト、されど数バイト」
BOMの沼は、データ変換を担当するエンジニアが一度は通る洗礼です。BOMあり/なしの仕様差に翻弄されて夜を明かした経験は、勲章のようなものかもしれません。しかし、データ変換の本質は「コードの差異に悩むこと」ではなく、「届けたい価値を淀みなく繋ぐこと」です。
今回検証したように、DTRを活用すればBOMを含めた文字コード制御を自動化できます。不毛な文字化けトラブルから解放され、アーキテクチャ設計やロジックの実装に集中できるようになります。
We Are Hiring!
-
DTRは、BIPROGYが提供するデータ変換ツールです。DTRを使用することで、文字コードやファイル形式、レイアウトの違いに悩まされることなく、簡単にデータ変換することができます。また、データ変換の結果を使用して、高度なシステム連携を実施することができます。詳細は、以下をご覧ください。
https://www.biprogy.com/solution/service/dtr.html ↩
