Vimで文字コードを変更して保存する(fileencoding/fenc)
Shift-JISで書かれたファイルをUTF-8で保存し直したいだけなのに、どのオプションをいじればいいのか毎回忘れます。保存時の文字コードを決めるのはfileencoding(短縮形fenc)オプションです。
目次(9項目)
| コマンド | これだけ覚える |
|---|---|
:set fileencoding=utf-8 / :set fenc=utf-8 | 保存時の文字コードを指定 |
:w | 指定した文字コードで実際に保存(これを忘れると反映されない) |
:set fileencoding? | 現在の設定を確認 |
保存する文字コードを指定する
:set fileencoding=utf-8
:w
短縮形を使えばこう書けます。
:set fenc=utf-8
:w
よく使う指定はこのあたりになります。
| 文字コード | 指定例 |
|---|---|
| UTF-8 | fenc=utf-8 |
| Shift-JIS | fenc=shift-jis |
| EUC-JP | fenc=euc-jp |
| Windows(CP932) | fenc=cp932 |
指定しただけでは保存されない
ここが引っかかりやすい点です。:set fenc=を実行した時点では、バッファ内のエンコーディング指定が変わるだけで、ディスク上のファイルはまだ書き換わっていません。必ず続けて:wを実行して初めてファイルに反映されます。エンコーディングを変えたのに保存を忘れて閉じてしまい、変更が消えたと勘違いすることがあるので注意が必要です。
文字コードごとに保存を分けたいとき
同じディレクトリ内に複数の文字コードのファイルが混在するプロジェクトでは、ファイルタイプやディレクトリごとに保存時の文字コードを自動で切り替えたくなることがあります。autocmdと組み合わせれば、特定の拡張子やパスパターンに応じてfileencodingをあらかじめ設定しておけます。
autocmd BufReadPost *.csv setlocal fenc=cp932
毎回手動で:set fenc=を打つより、こうしたルールを決めておくほうがミスを減らせます。
fileencodingとencodingの違い
名前が似ていますが、指しているものが違います。
fileencoding | encoding | |
|---|---|---|
| 対象 | そのバッファを保存するときの文字コード | Vim内部でテキストを処理する文字コード |
| 変更の影響範囲 | そのファイルの保存形式だけ | 表示・内部処理全体 |
| 通常の運用 | ファイルごとに調整する | utf-8で固定しておく |
encodingを変更すると表示や内部処理全体に影響するため、通常はutf-8のまま固定しておき、ファイルごとの保存形式だけをfileencodingで調整するのが安全な運用になります。現在の設定を確認する方法は別記事で扱っています。
fencで指定し、必ず:wまでセットで実行します。内部処理用のencodingとは役割が違うので混同しないよう注意してください。
古いシステムの設定ファイルがShift-JISで、UTF-8のまま保存して文字化けさせてしまったことがあります。それ以来、既存ファイルを編集する前に必ず現在の文字コードを確認する癖がつきました。fencで変換した直後に:wを忘れて「反映されない」と焦ったことも一度や二度ではありません。
化けたときは開き直す
開いた時点で文字化けしている場合、保存側の fileencoding をいじっても直りません。読み込みに失敗しているので、正しい文字コードを指定して開き直します。
:e ++enc=cp932 " Shift-JIS(Windows)として読み直す
:e ++enc=euc-jp " EUC-JP として読み直す
:e! " 元の判定で読み直す
++enc= は開き直すときだけの指定なので、バッファを編集していると実行できません。編集してしまった場合は :e! で捨ててから指定し直します。正しく読めた状態で :set fenc=utf-8 と :w を実行すれば、変換して保存できます。
判定の順番を決める fileencodings
開いたときにどの文字コードと判断するかは fileencodings(複数形)の並び順で決まります。左から順に試し、矛盾なく読めたところで確定します。
:set fileencodings?
set fileencodings=ucs-bom,utf-8,cp932,euc-jp,latin1
並び順には理由があります。ucs-bom を先頭に置くのはBOM付きのファイルを取り違えないため、latin1 を最後に置くのはどんなバイト列でも読めてしまい、先に置くと後ろが試されなくなるためです。日本語のファイルを扱うなら cp932 と euc-jp を utf-8 の後ろに入れておくと、たいていの化けは起きなくなります。
BOMが付くかどうか
UTF-8で保存したのに他のツールが読めない、という場合はBOMの有無が食い違っています。Vimでは bomb というオプションが持っていて、これも保存時に反映されます。
:set bomb? " 現在の設定を見る
:set bomb " BOM を付けて保存する
:set nobomb " BOM を付けない
WindowsのツールにはBOMを前提にするものがあり、逆にUnix系のツールはBOMがあると先頭の行を読み違えます。どちらに渡すファイルなのかで決めてください。改行コードのほうを直したいときはfileformatの記事にまとめています。
まとめ
fileencoding(fenc)は保存時の文字コードを制御するオプションで、変更後は必ず保存操作とセットで使います。読み込み時の文字コードを変えたい場合は別の方法が必要になります。文字コードと改行コードは別々の設定です。改行のほうを直したいときはfileformatの記事を見てください。開いた時点で文字化けしている場合は保存側のfileencodingではなく読み込み側の設定の問題なので、先に開き直しを試すのが順序として正しいです。保存し直したあとは、意図した文字コードになっているかを:set fileencoding?で確認しておくと安全です。思っていたのと違う値なら、保存の前にファイルの読み込み側がずれていた可能性が高くなります。