UTF-8のテキストファイルにはBOM有無の2種類がある
文字コードがUTF-8のテキストファイルには、BOMがあるファイルと無いファイルの2種類があります。
BOM(ボム)とは「バイトオーダーマーク(Byte Order Mark)」の通称で、Unicodeのテキストファイルであることを明示するためにテキストファイルの先頭から2~4バイトを使って特殊文字を埋め込まれたデータのことを言います。
WindowsでのUnicodeは一般的にはUTF-8のことを指すことがほとんどです。UTF-8のBOMは、テキストファイルの先頭に「0xEF 0xBB 0xBF」の3バイトが埋め込まれます。
なお、UTF-7やUTF-16などの他の符号化形式の場合のBOMはUTF-8とは違うデータになります。
このBOMですが、ExcelでUTF-8のテキストファイルを扱う際に結構重要だったりします。というのも、文字コードがUTF-8でBOM無しのCSVファイルをダブルクリックした場合、UTF-8のデータであることを判定できず、Shift-JISとして開いてしまい文字化けしてしまいます。BOMが付いていればUTF-8と判定して文字化けは起こりません。
このような問題を回避するために、文字化けが発生しそうなテキストファイルかどうかの判定をするには、イチかバチかダブルクリックして文字化けするかどうかを見るか、ってことになってきます。
いちいちExcelで開くのは面倒なので、事前にVBAでBOMが付いているかどうかを判定する方法を紹介します。
BOMの判定を行うコード
以下の関数は、引数で渡されたテキストファイルの先頭3バイトにBOMが付いているかどうかを判定します。戻り値として、BOMがあればTrue、なければFalseを返します。
処理の内容はコメントにほとんど書いてますが、やっていることの概要は、引数のテキストファイルを先頭3バイト読み込んで、「0xEF 0xBB 0xBF」と同じかどうかを調べて、同じであればBOMが付いている、と判定しています。
なお、引数のテキストファイルが3バイト未満の場合はBOMなしを返します。
処理中でのテキストファイルの操作はバイナリデータを扱う方法で行っています。
バイナリデータを扱う方法の詳細については「VBAでバイナリファイルを読み込む(一括、1バイト、指定バイト)」をご参照ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
'// 引数:テキストファイルパス '// 戻り値:BOM存在チェック結果:True:BOMあり、False:BOMなし Function IsBomExists(a_sPath As String) As Boolean Dim fn '// ファイル番号 Dim iSize '// ファイルサイズ Dim i '// ループカウンタ Dim byData() As Byte '// バイナリデータ '// ファイル番号取得 fn = FreeFile '// バイナリ形式で引数のテキストファイルを開く Open a_sPath For Binary Access Read As #fn '// ファイルサイズ取得 iSize = LOF(fn) '/ 3バイト未満の場合 If iSize < 3 Then '// ファイルクローズ Close #fn '// BOMなし IsBomExists = False Exit Function End If '// 先頭3バイト読み込み ReDim byData(2) Get #fn, 1, byData(0) Get #fn, 2, byData(1) Get #fn, 3, byData(2) '// ファイルクローズ Close #fn '// 先頭3バイトがBOMの場合(0xEF(239)、0xBB(187)、0xBF(191)の場合) If byData(0) = 239 And byData(1) = 187 And byData(2) = 191 Then '// BOMあり IsBomExists = True '// 先頭3バイトがBOMではない場合 Else '// BOMなし IsBomExists = False End If End Function |
使い方
上のIsBomExists関数の使い方です。
BOMがあるかどうかを調べたいテキストファイルを引数として渡して、Boolean型の変数で受け取ります。BOMがついていれば戻り値にTrueが設定され、ついてなければFalseが設定されます。
1 2 3 4 5 6 7 8 9 10 11 |
Sub IsBomExistsTest() Dim sPath As String '// ファイルパス Dim bResult As Boolean '// 処理結果 '// sPath = "D:\test\UTF8-No-BOM.csv" '// BOMなしのファイルはFalseが返ってくる sPath = "D:\test\UTF8-BOM.csv" '// BOMありのファイルはTrueが返ってくる bResult = IsBomExists(sPath) Debug.Print bResult End Sub |