← Vim研究所

Vimで文字コードを確認・変換する(文字化けの直し方とfenc)

2026-08-03 公開 ・ 更新: 2026-10-29 ・

開いたファイルが文字化けしている、Shift-JISのファイルをUTF-8で保存し直したい。どちらも文字コードの話ですが、Vimでは確認・開き直し・変換で使うものが別々です。この記事では、いまの文字コードを確認し、化けていたら正しい文字コードで開き直し、最後に変換して保存する、という順に進めます。

目次(9項目)
やりたいことこれだけ覚える
確認する:set fenc?(いま開いているファイルの文字コード)
文字化けを直す:e ++enc=cp932(文字コードを指定して開き直す)
変換して保存する:set fenc=utf-8 のあと :w

いまの文字コードを確認する

:set fenc?

オプション名の末尾に?を付けると、現在の値が画面下に出ます。fencはfileencodingの短縮形で、Vimがこのファイルを何の文字コードとして読んだか、そして保存するときに何で書き出すかを表します。Shift-JISのファイルならcp932、UTF-8ならutf-8と出ます。

コマンド確認できること
:set fenc?このファイルの文字コード(fileencoding)
:set enc?Vim内部で使う文字コード(encoding)
:set fencs?開くときに試す候補の並び(fileencodings)
:set ff?改行コード(fileformat)

:set fenc?が空欄になるのは、:newで作ったばかりのバッファのように、まだファイルを読んでいないときです。空欄はencodingと同じ文字コードで保存するという意味で、化けているかどうかの判断材料にはなりません。

文字化けだと思っていた不具合が、実は改行コード(fileformat)の食い違いだったということもあります。行末に^Mが並んでいるなら文字コードではなく改行コードの問題なので、:set ff?も一緒に見ておくと切り分けが早く済みます。

ステータスラインに常に出しておく

文字コードの違うファイルを行き来する作業では、毎回打つより常に見えているほうが化けに早く気づけます。

set statusline=%f\ %{&fenc!=''?&fenc:&enc}/%{&ff}

fencが入っていればその値を、空ならencodingの値を出し、後ろに改行コードを並べます。ステータスラインが出ていないならlaststatusを2にします。lightlineやlualineで管理している場合はstatuslineを直接書き換えず、プラグイン側の文字コード表示のコンポーネントを有効にします。

encoding・fileencoding・fileencodingsの違い

名前が似た3つのオプションが、それぞれ別の場面を受け持っています。ここを取り違えると、直す場所を間違えます。

オプション受け持つ場面普段の扱い
encoding(enc)Vimが内部でテキストを持つ文字コードutf-8で固定。触らない
fileencodings(fencs)ファイルを開くときに試す候補の並びvimrcで1回決める
fileencoding(fenc)読んだ結果であり、保存するときの文字コードファイルごとに変える

開くときはfileencodingsの候補から1つが選ばれてfileencodingに入り、そこからencodingへ変換して画面に出します。保存するときは逆にencodingからfileencodingへ変換して書き出します。:set enc?がutf-8以外なら、ファイルごとの話ではなく設定全体の問題なので、先にvimrcでset encoding=utf-8にしてください。Neovimはutf-8固定で変えられません。

文字化けしたら:e ++enc=で開き直す

開いた時点で化けているなら、読み込みの判定を外しています。保存側のfileencodingをいじっても直らないので、正しい文字コードを指定して読み込み直します。

:e ++enc=cp932        " Shift-JIS(Windows)として読み直す
:e ++enc=euc-jp       " EUC-JP として読み直す
:e ++enc=iso-2022-jp  " JISコード(メールなど)として読み直す
BEFORE
??????????
:e ++enc=cp932
AFTER
こんにちは

Shift-JISのファイルをEUC-JPとして読むと、変換できないバイトが?に置き換わって上のようになります。:e ++enc=cp932で読み直すと「[converted]」と出て正しく表示され、:set fenc?もcp932に変わります。日本語のファイルなら候補はcp932・euc-jp・iso-2022-jpの3つでほぼ足り、順に試せばたいてい当たります。

編集してしまうと開き直せない

:e ++enc=はファイルを読み直すコマンドなので、未保存の変更があるとE37で止まります。化けに気づかず何か打ってしまったときは、!を付けて変更を捨てながら指定します。

:e! ++enc=cp932       " 変更を捨てて cp932 で読み直す

化けた状態のまま:wすると、元のバイト列が失われて戻せなくなります。化けに気づいたら、何も保存せずに開き直すのが鉄則です。

文字コードの見当がつかないとき

候補を順に試すより先に、バイト列を見てしまうほうが早いこともあります。xxdに通すと16進数で表示されます。

:%!xxd                " 16進ダンプに変換する
:%!xxd -r             " 元に戻す(保存前に必ず実行する)

ひらがなの「こ」なら、UTF-8はe3 81 93の3バイト、Shift-JISは82 b1、EUC-JPはa4 b3の2バイトです。先頭がef bb bfならBOM付きのUTF-8、1b 24 42(ESC $ B)が出てくればJISコードです。OSのfileコマンドで調べる手もありますが、macOSで試すとShift-JISはunknown-8bit、EUC-JPはiso-8859-1と出て、日本語の判定には使えませんでした。

使ってみて

古いWindows由来のCSVファイルを開くたびに文字化けしていましたが、原因がCP932だと分かってからは:e ++enc=cp932を反射的に打つようになりました。何度も同じ文字コードで開き直すなら、次の節のfileencodingsを見直したほうが根本的な解決になると気づいたのは、しばらく経ってからでした。

++encとfencは何が違うか

どちらも文字コードを指定するので混同しやすいのですが、働く場面が逆です。++enc=は読み込むときにバイト列をどう解釈するかの指定で、ファイルの中身は1バイトも変えません。fencは保存するときに何へ変換して書き出すかの指定で、:wした時点でファイルのバイト列が書き換わります。

化けているファイルに:set fenc=utf-8と:wを実行すると、化けた解釈のままUTF-8に変換して保存され、壊れたファイルができあがります。順番は必ず「++encで正しく読める状態にする」が先、「fencで変換して保存する」が後です。++enc=cp932で読み直した直後はfencもcp932になっているので、そのまま:wすればShift-JISのまま保存されます。

開くときの判定順を決めるfileencodings

開いたときにどの文字コードと判断するかは、fileencodingsの並び順で決まります。左から順に試し、矛盾なく読めた最初の候補で確定します。Vim(encodingがutf-8のとき)もNeovimも、既定値はucs-bom,utf-8,default,latin1で、cp932もeuc-jpも入っていません。手元のVim 9.1とNeovim 0.12で試すと、どちらもShift-JISのファイルはlatin1として読まれて化けました。日本語のファイルを開くなら、vimrcで候補を足しておきます。

set fileencodings=ucs-bom,utf-8,euc-jp,cp932,latin1

並び順にはそれぞれ理由があります。

JISコード(ISO-2022-JP)のファイルも扱うなら、iso-2022-jpを先頭に置く必要があります。JISコードは7ビットのバイトだけでできているのでutf-8としても読めてしまい、後ろに置くとエスケープシーケンスがそのまま見える化け方になります。ただし先頭に置くと、英数字だけのファイルまでfencがiso-2022-jpになります。そこへ日本語を足して保存すると、ファイルがJISコードで書き出されました。JISのファイルを開く機会が無いなら入れないほうが安全です。

短いファイルや決まったディレクトリの古いファイルは、自動判定に任せず開き直しで決め打ちするほうが確実です。fileencodingsはグローバルなオプションなので、特定のファイルのためだけにautocmdで書き換えると、ほかのファイルを開くときにも効いてしまいます。

文字コードを変換して保存する(fenc)

正しく読めている状態で、保存時の文字コードを指定してから書き出します。

:set fenc=utf-8
:w
文字コード指定例
UTF-8fenc=utf-8
Shift-JIS(Windows)fenc=cp932
EUC-JPfenc=euc-jp
JISコードfenc=iso-2022-jp

引っかかりやすいのは、:set fenc=を実行しただけではディスク上のファイルが変わらない点です。変わるのはバッファの設定だけで、このとき'modified'が立つので、そのまま:qしようとするとE37で止められます。必ず続けて:wを実行し、保存後に:set fenc?で意図した値になっているかを確かめます。Shift-JISのファイルを:e ++enc=cp932で読み、:set fenc=utf-8と:wで保存すると、中身は82 b1からe3 81 93のUTF-8に変わりました。

Windowsの古いツールに渡すCSVのように、決まった拡張子をいつも同じ文字コードで書き出したいなら、読み込み後にfencを設定しておけます。

autocmd BufReadPost *.csv setlocal fenc=cp932

これは保存時の変換だけを決めるもので、読み込みの判定には影響しません。UTF-8で書かれたCSVでも、保存すればcp932に変換されます。

使ってみて

古いシステムの設定ファイルがShift-JISで、UTF-8のまま保存して文字化けさせてしまったことがあります。それ以来、既存ファイルを編集する前に:set fenc?で文字コードを確認する癖がつきました。fencを変えた直後に:wを忘れて「反映されない」と焦ったことも一度や二度ではありません。

BOMが付くかどうか

UTF-8で保存したのにほかのツールが読めないときは、BOMの有無が食い違っています。BOMはfencではなくbombというオプションが持っていて、これも保存時に反映されます。BOM付きのUTF-8を開くとbombが自動で立ちます。

:set bomb?            " 現在の設定を見る
:set bomb             " BOM を付けて保存する
:set nobomb           " BOM を付けない

WindowsのツールにはBOMを前提にするものがあり、逆にUnix系のツールはBOMがあると先頭の行を読み違えます。どちらに渡すファイルなのかで決めてください。

まとめ

文字コードは:set fenc?で確認し、開いた時点で化けていれば:e ++enc=で読み込みの解釈を変えて開き直します。正しく読めてから:set fenc=と:wで変換して保存する、という順番を崩さなければ、ファイルを壊すことはありません。同じ化け方を繰り返すなら、fileencodingsの並びを見直します。

関連記事

← Vim研究所 トップへ戻る