Macで文字コードを変換する|化けた書類を直す手順

mac 文字コード 変換で検索する人の多くは、変換のコマンドを知りたいのではなく、目の前の書類が何のコードで保存されているのか分からない状態で止まっています。開いたら記号の羅列になった、ターミナルでは読めるのにアプリでは化ける、変換したつもりが一部の文字だけ消えた。この記事では、いまのコードを読む手順から始めて、Macに標準で入っている変換の道具の使い分けと、変換が失敗したときの読み方までを順番に整理します。

文字化けは、中身のコードと読み手の推測がずれたときに起きる

テキストファイルは、文字そのものではなく数値の並びとして保存されています。どの数値をどの文字として読むかの取り決めが文字コードで、保存した側と開いた側が別の取り決めを使うと、画面には別の文字が並びます。壊れているのではなく、読み方が合っていないだけという状態です。

日本語の書類で出会う取り決めは主に4つです。UTF-8は現在の標準で、Macの既定でもあります。Shift_JISはWindowsの日本語環境で長く使われてきたもので、その拡張であるCP932も同じ系統です。EUC-JPは古いUNIX系の環境で使われ、ISO-2022-JPはメールの本文で使われてきました。取引先から届くCSVや、古い社内システムが書き出したログには、いまもこれらが混ざります。

ファイルの中に「自分は何のコードか」を書く欄はありません。唯一の手掛かりはBOMと呼ばれる先頭の数バイトの印で、これも付いていないファイルが普通にあります。そのため、開いた側は中身の並びから推測します。推測が当たれば読め、外れれば化けます。同じファイルがアプリによって読めたり読めなかったりするのは、この推測の実装が相手ごとに違うためです。

作業の順番は決まっています。推測に任せず、まず現在のコードを読む。次に、行き先のコードを決める。最後に変換する。この3段を飛ばして変換のコマンドだけを打つと、化けたファイルをさらに化けた状態に固定してしまいます。

いまのコードを読む。2つのコマンドで足りる

Macには変換の前に状態を読む道具が入っています。最初に打つのはfileです。

file -I report.csv
file --mime-encoding report.csv

fileはファイルシステムの検査、magicの検査、言語の検査の順に試し、最初に当たった答えを返します。-Iを付けると人が読む言い回しではなくMIMEの形で出るため、text/plain; charset=us-asciiのように種類と文字集合が並びます。--mime-encodingはそのうち文字集合だけを出します。ここでutf-8と返れば変換は不要で、iso-8859-1やunknown-8bitのような答えが返ってきたときは、日本語のコードを推測できていない状態です。

もう1つはtextutilの情報表示です。

textutil -info report.txt

このコマンドはCocoaのテキスト機能を通してファイルを読み、形式とエンコーディングを報告します。fileが並びから推測するのに対し、こちらはmacOSのアプリが実際に開くときと同じ経路をたどるため、テキストエディットで開いたときにどう解釈されるかの目安になります。2つの答えが食い違う場合は、そのファイルがどちらの推測にも確実に当たらない並びを持っているという意味で、変換の前に元の出どころを確かめる価値があります。

バイトの並びを直接見たいときはxxdかhexdumpが使えます。先頭にef bb bfが並んでいればUTF-8のBOM付き、ff feかfe ffならUTF-16です。ここまで見れば、推測ではなく事実として現在のコードを決められます。

iconvで変換する。基本形と、失敗したときの読み方

macOSに標準で入っている変換の道具はiconvです。変換元と変換先を指定して、結果を標準出力に流します。

iconv -f SHIFT_JIS -t UTF-8 old.csv > new.csv

-fが変換元、-tが変換先です。元のファイルを書き換えるのではなく標準出力に出す作りなので、行き先を別の名前にしておけば元のファイルが残ります。同じ名前に流し込むとファイルが空になるため、変換元と行き先の名前は分けます。

使える取り決めの名前は環境ごとに違います。手元で使える名前の一覧は次の1行で出ます。

iconv -l

SHIFT_JISとCP932はよく混同されますが、後者はMicrosoftが独自に足した文字を含む拡張です。丸で囲んだ数字やローマ数字、いわゆる機種依存文字が入った書類をSHIFT_JISとして変換すると、その文字だけが落ちます。Windowsから届いたCSVを扱うときはCP932を先に試すほうが取りこぼしが少なくなります。

変換が完全にできなかったとき、iconvは変換できなかった文字の数を標準エラー出力に出します。この数が0でなければ、出来上がったファイルにはどこかに欠けがあります。-cを付けると読めない文字を捨てて処理を続け、-sを付けると報告そのものを止めます。急いでいるときに-cを足したくなりますが、業務の書類では欠けた場所が分からなくなるほうが高くつきます。まず報告を読み、数が多ければ変換元の指定が違う可能性を先に疑います。

textutilは、エンコーディングと形式を同時に扱える

iconvは文字コードだけを扱います。書類の形式まで変える必要があるときはtextutilが窓口になります。標準テキスト、HTML、RTF、Word形式などを相互に変換でき、その際の出力エンコーディングも指定できます。

textutil -convert txt -encoding UTF-8 report.rtf
textutil -convert txt -inputencoding CP932 -encoding UTF-8 -output new.txt old.txt

-encodingは出力側のエンコーディングで、指定しなければUTF-8になります。-inputencodingは入力側を強制する指定で、こちらを省いた場合はBOMから判断します。BOMが付いていない日本語のファイルでは判断が外れるため、変換元がはっきりしているなら-inputencodingで明示したほうが結果が安定します。どちらの指定も、そのエンコーディングで扱えないときは処理が失敗して止まります。黙って欠けた状態で書き出さない作りなので、業務の書類ではiconvの-cより安全側に寄っています。

-outputで行き先の名前を決められるほか、-stdinと-stdoutを使えばパイプの途中に挟めます。-stripを付けると入力側が持っていた作成者やタイトルなどの情報を引き継がずに書き出します。形式の変換で相手に渡す前に、余分な情報を落としておきたい場面で使えます。

nkfを入れるかどうかは、作業の頻度で決まる

日本語の文字コードの話でよく出てくるnkfは、macOSに標準では入っていません。/usr/binを見ても実体は無く、使うにはパッケージ管理の仕組みで自分で追加します。よく参照される指定は次の並びです。

-w : UTF8コードを出力(BOM無し) -e : EUCコードを出力 -s : Shift-JISコードを出力 -j : JISコード(ISO-2022-JP)を出力 -Lu : unix改行形式(LF)に変換 -Lw : windows改行形式(CRLF)に変換 -Lm : mac改行形式(CR)に変換 -g(--guess) : 文字コード自動判別の結果を表示 --overwrite : 元のファイルを上書きする 出典: miginihitsuji.com

標準の道具との違いは3つあります。1つ目は自動判別で、-gを付けると推測した結果だけを教えてくれるため、変換元を指定せずに調べられます。2つ目は上書きで、--overwriteを付けると別名のファイルを作らずに済みます。3つ目は改行コードの変換を同じコマンドで指定できることです。

判断の基準は頻度です。文字コードの変換が月に数回なら、標準で入っているiconvとtextutilで足ります。毎日のように届くファイルを処理するなら、判別と上書きを1行で済ませられる分だけ作業が軽くなります。追加する場合も、自動判別の結果をそのまま信用せず、変換後にfile -Iで確かめる手順は残したほうが安全です。

macでファイルの文字コードを変換する『nkfコマンド』の使い方とオプション一覧 | かわたま.net 出典: web-generalist.com

改行コードのずれは、文字コードとは別の問題

変換したのに1行目だけがおかしい、末尾に見えない文字が付いてくる、といった症状は文字コードではなく改行コードの話です。行の終わりを表す印は環境ごとに違い、UNIX系とmacOSはLF、WindowsはCRとLFの2文字、古いMac OSはCRを使っていました。

fileはこの違いも報告します。with CRLF line terminatorsと出ていれば、Windowsで書き出されたファイルです。シェルで1行ずつ処理すると、末尾のCRが値の一部として残り、比較が通らない原因になります。CSVを読み込むプログラムで最後の列だけ値が合わないときは、ここを疑うと早く片付きます。

改行だけを変えるなら、標準の道具ではtrやsedで処理できます。iconvは文字コードを扱うコマンドで、改行の変換は担当しません。1つのコマンドで両方を済ませたい場合が、先のnkfを入れる動機になります。

文字コードと改行コードは独立しているため、切り分けの順番も決まっています。まずfile -Iで文字集合を見て、次にfileの人が読む側の出力で改行の記述を見る。この2つを分けて読めば、どちらを直せばよいかで迷う場面は減ります。

CSVが化けるときに見る2か所

実務でいちばん多いのがCSVです。相手の環境で開けないと言われたときに見る場所は、文字コードとBOMの2か所に絞られます。

Windowsの表計算ソフトは、CSVを開くときにその環境の既定のコードで読もうとします。UTF-8で保存したファイルをそのまま渡すと、日本語の部分が化けます。先頭にUTF-8のBOMが付いていると、UTF-8だと判断できるアプリが増えます。逆に、プログラムで読み込む相手にBOM付きを渡すと、1列目の見出しの先頭に見えない文字が混ざり、列名の一致に失敗します。

つまり、正解は相手によって変わります。人が表計算ソフトで開くならBOM付きのUTF-8かCP932、プログラムが読むならBOMなしのUTF-8が無難です。どちらを渡したのかを自分で分かっている状態にしておくことが、やり直しを減らす唯一の手です。

BOMを付ける、あるいは外す操作は、変換と同時に扱えます。iconvの変換先にUTF-8-MACのような名前を選ぶと正規化の形まで変わってしまうため、単純にUTF-8へ寄せたいときはUTF-8を指定します。濁点や半濁点が分解された形で保存されるのはこの正規化の違いによるもので、ファイル名の検索が当たらない原因にもなります。

変換の作業で往復が増えている場所

文字コードの作業は、判断に使う情報が3か所に散っています。対象のファイルがどこにあるか、file -Iが何と答えたか、そして変換のコマンドをどう書くか。フォルダを見る窓とコマンドを打つ窓とAIに聞く窓が別々に開いていると、1件あたり3回以上の切り替えが入り、届いたファイルの数だけ積み上がります。

フォルダとターミナルとAIが同じ窓にある状態なら、対象を選んだまま現在のコードを読み、そのまま変換の1行を打ち、出来上がったファイルを同じ一覧で確かめられます。変換は「読む、決める、書き出す、確かめる」の4段を繰り返す作業なので、往復が減ると確かめる工程を省きにくくなります。

道具の側で何ができるかはできることに、Finderやほかのファイル管理との違いは他のファイル管理との比較にまとまっています。日本語以外の環境で使う場合の範囲は対応言語、外出先から手元のMacの作業を確かめる使い方はiPhone・iPadから続きをに整理されています。費用の目安は料金、判断に迷いやすい点はよくある質問にあります。

まず変えるべきは、変換のコマンドを打つ前にfile -Iを1行挟む習慣です。現在のコードが事実として分かっていれば、変換先の指定を間違える場面はほとんど残りません。

よくある質問

ファイルの文字コードを調べるコマンドはどれですか?

標準で入っているものは file です。file -I と打つと text/plain; charset=utf-8 のようにMIMEの形で文字集合まで出ます。文字集合だけを見たいときは file --mime-encoding を使います。macOSのアプリが実際にどう解釈するかを知りたいときは textutil -info が近い答えを返します。

Shift_JISとCP932はどちらを指定すればよいですか?

Windowsから届いたファイルなら、まずCP932を試してください。CP932はShift_JISにMicrosoftが独自に足した文字を含む拡張で、丸で囲んだ数字やローマ数字が入っている書類をSHIFT_JISとして変換すると、その文字だけが落ちます。手元で使える名前の一覧は iconv -l で確認できます。

iconvで一部の文字だけが消えるのはなぜですか?

変換先のコードにその文字が存在しない場合、iconvは代替の文字を出力し、変換できなかった数を標準エラー出力に報告します。-c を付けると読めない文字を捨てて処理を続けますが、欠けた場所が分からなくなります。報告された数が0でないときは、まず変換元の指定が合っているかを確かめてください。

nkfはMacに最初から入っていますか?

入っていません。/usr/bin に実体が無く、使うにはパッケージ管理の仕組みで自分で追加します。変換が月に数回であれば標準のiconvとtextutilで足ります。毎日ファイルが届くなら、自動判別の-gと上書きの--overwriteを1行で済ませられる分だけ作業が軽くなります。

記事一覧へ戻る