Vimで開いているファイルの文字コードを確認する方法
画面に文字化けが出たとき、今のファイルがどの文字コードとして認識されているかをまず確認したくなります。毎回コマンドを打つのが面倒なら、ステータスラインに常時表示させておく方法もあります。
目次(9項目)
その場で確認する
:set enc?
encodingの末尾に?を付けて実行すると、現在の値が画面下部に表示されます。ただしこれはVim内部で使っているencodingの値であって、ファイルの保存に使われるfileencodingとは別の値です。ファイルが今どの文字コードとして扱われているかを知りたい場合は、こちらも合わせて確認すると確実です。
:set fenc?
| コマンド | 確認できること |
|---|---|
:set enc? | Vim内部で使う文字コード(encoding) |
:set fenc? | ファイルの保存に使う文字コード(fileencoding) |
:set ff? | 改行コード(fileformat) |
ステータスラインに常時表示する
set statusline=%{&fenc!=''?&fenc:&enc}/%{&ff}
この設定を入れておくと、fileencodingが設定されていればその値を、空であればencodingの値をステータスラインに表示します。末尾の%{&ff}は改行コード(fileformat)も一緒に表示する指定で、文字コードと改行コードは同時に確認したくなることが多いのでセットにしておくと便利です。
ステータスラインには他にも表示したい情報が色々あるはずなので、実際にはファイル名や行番号などと組み合わせてvimrcやinit.luaに設定しておくのが一般的です。laststatusの設定と合わせて調整すると使いやすくなります。表示条件については別記事で扱っています。
lightline/lualineなどのプラグインを使っている場合
ステータスラインをプラグインで管理している場合は、statuslineを直接書き換えるのではなく、そのプラグイン側の設定項目で文字コードの表示を有効にする形になります。多くのステータスラインプラグインには文字コード・改行コード表示用のコンポーネントが標準で用意されているので、まずはプラグインのドキュメントで対応する項目を探すほうが早いことが多いです。
:set enc?/:set fenc?で十分です。頻繁に文字コードの違うファイルを扱うなら、ステータスラインに常時表示させておくと切り替えのたびに気づきやすくなります。
複数のレガシーシステムのログファイルを行き来する作業で、ファイルごとに文字コードがバラバラだったため、ステータスラインに表示する設定を入れてから文字化けに気づくのが早くなりました。都度:set enc?を打っていた頃は、気づかず編集を進めてから文字化けに驚くことがよくありました。常時表示にしてからは、開いた瞬間に違和感のある表示に気づけるようになったのが一番大きい変化でした。
改行コードも一緒に確認する
文字化けだと思っていた不具合が、実は改行コード(fileformat)の不一致だった、ということもあります。:set ff?で確認でき、unix・dos・macの3種類が主な値になります。文字コードとあわせてこちらも確認しておくと、原因の切り分けが早くなります。
どちらが原因かを切り分ける
文字化けの原因は、読み込みの判定を外している場合と、Vim全体の encoding が合っていない場合に分かれます。前者ならファイルごとに直せますが、後者は設定ファイルを直すことになります。
:set encoding? " Vim内部の文字コード(通常は utf-8)
:set fileencoding? " いま開いているファイルの文字コード
encoding が utf-8 でないなら、まずそちらを直します。encoding が正しく、fileencoding だけが実際と違うなら、:e ++enc=cp932 のように指定して開き直せば直ります。
判定を外しやすいファイル
Vimの自動判定は、バイト列として矛盾が無いかを見ています。そのため、日本語がごく少ない Shift-JIS のファイルは utf-8 として読めてしまい、日本語の部分だけが化けます。ソースコードのコメントに数語だけ日本語が入っている、というファイルが典型です。
短いファイルほど判定材料が少ないので外しやすくなります。プロジェクト全体の文字コードが分かっているなら、拡張子やディレクトリで決め打ちしてしまうほうが確実です。
autocmd BufReadPre */legacy/* setlocal fileencodings=cp932,utf-8
バイト列を直接見る
判定を疑うなら、実際のバイト列を見るのがいちばん早く済みます。xxd に通せば16進数で表示され、元に戻すこともできます。
:%!xxd " 16進ダンプに変換する
:%!xxd -r " 元に戻す
日本語がUTF-8なら1文字が3バイト、Shift-JISなら2バイトで並びます。先頭に efbbbf があればBOM付きのUTF-8です。変換したまま保存すると壊れるので、必ず -r で戻してから保存してください。保存時の文字コードの指定はfileencodingの記事にまとめています。
まとめ
文字コードの確認は:set enc?/:set fenc?で即座にでき、頻繁に確認するならステータスラインに常時表示しておくのが実用的です。保存時の文字コード変更は別記事で扱っています。