MENU

CSVの文字化けを防ぐには?UTF-8とShift_JISの違いをExcelとPythonで実務向けに整理

CSVの文字化けを防ぐには?UTF-8とShift_JISの違いをExcelとPythonで実務向けに整理

CSVの文字化けは、ファイルの中身が壊れているのではなく、保存時の文字コードと開く側の想定がずれているときに起きることがほとんどです。

先に答えを書くと、いま新しく作るCSVは UTF-8を基本 にしつつ、Excelでそのまま開かせる必要がある場面では BOM付きUTF-8 を使うのが実務では安全です。古い業務システムや一部のWindows向け連携では、相手側の指定に合わせて Shift_JIS系(実務ではcp932を含む扱い) を選ぶ場面が残ります。

  • UTF-8: 多言語に強く、WebやAPI、Pythonとの相性がよい
  • Shift_JIS: 日本語Windowsの古い運用でまだ使われる
  • Excelで文字化けしやすい点: UTF-8でもBOMなしだと意図どおり開けないことがある
  • Pythonの基本: open(..., encoding=...) を必ず明示する
  • 実務の判断: 「誰が何で開くか」を先に決めると失敗しにくい

ここがポイント: CSVの対策は「UTF-8が正しいか」ではなく、「保存時と読込時で同じ文字コードを使えているか」で決まります。

目次

まず押さえたい前提環境

この記事は、次のような場面を想定しています。

  • Windows版ExcelでCSVを直接開く
  • Python 3.12系でCSVを読み書きする
  • 日本語を含む顧客名、住所、商品名、メモ列を扱う
  • CSVをメール添付、共有フォルダ、業務システム連携で受け渡す

バージョン差で細かい挙動は変わりますが、Microsoftはサポート記事で、UTF-8のCSVはBOM付きなら通常どおり開ける と案内しています。BOMがない場合は、Excelの「データの取得」から読み込む方法が案内されています。

UTF-8とShift_JISは何が違うのか

ここを曖昧にすると、対策も曖昧になります。違いはかなり実務的です。

UTF-8

現在の標準候補 です。Web、API、JSON、Markdown、データ基盤、Pythonの多くの処理系で前提になっています。

向いている場面は次のとおりです。

  • 日本語と英語が混ざるCSV
  • 絵文字や機種依存文字に近いデータを含む可能性がある
  • Python、Node.js、GAS、API連携に流す
  • 将来的に他システムへ再利用する

Shift_JIS

日本語Windowsの業務運用で長く使われてきた文字コードです。今でも古い基幹系、会計ソフト向け取込、既存マクロ運用では指定されることがあります。

ただし、UTF-8より扱える文字の幅が狭く、次のような場面で詰まりやすくなります。

  • 一部の記号や特殊文字が保存できない
  • システム間連携で再利用しにくい
  • Web系のツールと混ぜると文字コード指定が増える

実務で重要な見分け方

「UTF-8とShift_JISのどちらが優れているか」ではなく、次で決めるのが現実的です。

  • Excelでダブルクリックして開く運用か
  • 取込先システムが文字コードを明示しているか
  • PythonやAPIで後続処理するか
  • 日本語以外の文字が混ざる可能性があるか

新規設計ならUTF-8寄り、既存システム連携なら相手指定優先。まずはこの整理で十分です。

文字化けが起きる典型パターン

CSVの中身そのものより、開き方で失敗するケースが多いです。

1. UTF-8で保存したのにExcelで直接開いた

UTF-8のCSVでも、Excel側が期待する形で読めないと、日本語が崩れることがあります。特に BOMなしUTF-8 をそのまま開く運用は要注意です。

2. Shift_JIS指定のファイルをUTF-8として読んだ

Pythonやエディタで読み込むと、 のような崩れではなく、見た目に日本語が化けた状態になります。

3. 書き出しはUTF-8、読み込みはシステム既定のまま

Pythonの open() は、文字コードを省略すると環境依存になります。Python公式ドキュメントでも、encodingを明示することが推奨 されています。Windowsと他OSで挙動差が出やすい部分です。

最初に確認すべき判断フロー

迷ったら、次の順で決めると実務でぶれにくくなります。

  1. 開く人は何を使うかを確認する
  2. 取込先システムの指定文字コードを確認する
  3. 指定がなければUTF-8を第一候補にする
  4. Excel直接オープンが前提ならBOM付きUTF-8も検討する
  5. Pythonでは保存側も読込側も encoding を固定する

Excelで文字化けを防ぐ方法

Excel運用では、保存方法と開き方を分けて考えると整理しやすいです。

そのまま開かせたいならBOM付きUTF-8を使う

Microsoftのサポート情報では、UTF-8のCSVはBOM付きなら通常どおり開ける とされています。社内で「CSVをダブルクリックして確認する」運用が多いなら、この条件がかなり重要です。

PythonでBOM付きUTF-8を書き出す最小例です。

import csv

rows = [
    ["id", "name", "note"],
    [1, "山田太郎", "東京本社"],
    [2, "佐藤花子", "見積確認中"],
]

with open("customers_utf8_bom.csv", "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

この utf-8-sig は、Pythonの utf_8_sig コーデックに対応しています。書き込み時にBOMを付け、読み込み時は先頭のBOMを読み飛ばせます。

BOMなしUTF-8を使うなら、Excelはインポートで開く

WebやAPI連携を前提にするなら、BOMなしUTF-8のほうが扱いやすい場面もあります。その場合は、Excelで直接開くのではなく、[データ] タブからテキスト/CSVとして取り込む ほうが安全です。

向いている場面は次のとおりです。

  • システムの標準出力がUTF-8
  • 他ツールでも同じCSVを使い回す
  • Excelは確認用で、元データは別にある

既存システム指定があるならShift_JIS系で出す

取込先が「Shift_JIS指定」「Windows向けCSV指定」なら、それに合わせます。勝手にUTF-8へ変えると、相手側で読めなくなることがあります。

Pythonでは次のように書けます。

import csv

rows = [
    ["code", "company", "address"],
    ["A001", "株式会社サンプル", "大阪市北区"],
]

with open("customers_sjis.csv", "w", newline="", encoding="cp932") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

実務では shift_jis より cp932 を使うほうが、Windows由来の日本語データと噛み合いやすい場面があります。相手先仕様に表記があるなら、その指定を優先してください。

Pythonでの基本の書き方

Pythonでは、CSVモジュールの使い方自体より、newline=''encoding 指定 が重要です。

読み込みの基本

import csv

with open("input.csv", newline="", encoding="utf-8") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

Pythonの csv モジュール公式ドキュメントでも、ファイルは newline='' で開くよう案内されています。改行が混ざる列やWindows環境で、余計な空行や解釈ずれを防ぎやすくなります。

Excel向けに安全寄りで書く例

import csv

records = [
    {"id": 1, "name": "高橋", "city": "横浜"},
    {"id": 2, "name": "田中", "city": "名古屋"},
]

with open("export_for_excel.csv", "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.DictWriter(f, fieldnames=["id", "name", "city"])
    writer.writeheader()
    writer.writerows(records)

pandasで読む場合

pandas.read_csv() でも encoding を明示できます。

import pandas as pd

# UTF-8のCSVを読む
utf8_df = pd.read_csv("sales_utf8.csv", encoding="utf-8")

# Shift_JIS系のCSVを読む
sjis_df = pd.read_csv("sales_sjis.csv", encoding="cp932")

ファイルごとに文字コードが混ざる現場では、「読めたから正しい」とは限りません。列名や先頭数行を見て、日本語が崩れていないか確認するところまでを作業に含めるべきです。

入力例と出力例

ここでは、よくある日本語データを例にします。

入力データ

id,name,note
1,山田太郎,東京営業所
2,佐藤花子,見積書を送付済み

UTF-8系で正しく読めたときのイメージ

['id', 'name', 'note']
['1', '山田太郎', '東京営業所']
['2', '佐藤花子', '見積書を送付済み']

文字コードがずれたときの典型例

['id', 'name', 'note']
['1', '山田太郎', '譚ア莠ャ螟カ讌ュ謨ー']
['2', '佐藤花子', '隕句ソオ譖エ繧偵%騾∽ソ。縺ソ']

見た目は壊れていますが、CSVの区切り自体は残っていることが多いです。つまり、壊れているのは行構造ではなく、バイト列の解釈 です。

実務での使いどころ

CSVの文字コードは、単なる知識問題ではなく、運用設計の問題です。

社内でExcel確認が多いケース

  • 見積一覧
  • 顧客マスタの確認用出力
  • 月次レポートの配布

この場合は BOM付きUTF-8 か、相手指定のShift_JIS系が候補です。ダブルクリックで開く運用を変えないなら、ここを合わせるだけで問い合わせが減ります。

PythonやAPIへ流すケース

  • CSVを読み込んで集計する
  • JSONへ変換する
  • データ基盤へ取り込む

こちらは UTF-8を基準 にしたほうが後工程が楽です。日本語以外の文字が混ざっても扱いやすく、ツールごとの差も減らせます。

よくある失敗と対処

encoding を省略する

もっとも多い失敗です。環境依存になるので、手元では読めても別PCで崩れます。

対処は単純です。

  • 読み込み時に encoding を明示する
  • 書き出し時にも encoding を明示する
  • チーム内でCSVの標準文字コードを決める

utf-8utf-8-sig を混同する

どちらもUTF-8系ですが、Excelとの相性は同じではありません。

  • utf-8: WebやAPI向けでは扱いやすい
  • utf-8-sig: Excelへそのまま渡す用途で有利

Shift_JISで保存できない文字を含める

文字によっては、Shift_JIS系へ変換できずエラーになることがあります。顧客入力や外部データを扱うなら、保存前に例外処理を入れるか、UTF-8運用に寄せたほうが安全です。

text = "㈱テスト①"
encoded = text.encode("cp932", errors="strict")

このような場面では、エラーが出ること自体が重要な検知になります。無理に ignorereplace で落とすと、元データを静かに欠損させるおそれがあります。

代替手段と使い分け

CSVだけで押し切らないほうがよい場面もあります。

Excelブック(.xlsx)を使う

書式、改行、複数シート、文字コード問題をまとめて避けたいなら、CSVではなく .xlsx のほうが向いています。

向いている場面:

  • 人が目で確認するのが主目的
  • 列幅やシート構成も必要
  • 文字化け問い合わせを減らしたい

JSONを使う

システム連携なら、CSVよりJSONのほうが型情報や入れ子を持てます。UTF-8前提で扱いやすく、日本語の受け渡しでも混乱が少なくなります。

TSVを使う

カンマを含む文章列が多いなら、CSVよりTSVのほうが確認しやすいことがあります。ただし、文字コード問題そのものは別なので、encoding 指定は引き続き必要です。

迷ったときの実務向け結論

最後に、判断だけを短くまとめます。

  • 新規の自動処理やAPI連携: UTF-8
  • Excelで直接開く配布用CSV: UTF-8 with BOM(utf-8-sig
  • 既存の日本語Windows業務システム連携: 相手指定のShift_JIS系 / cp932
  • Pythonの原則: newline=''encoding=... を毎回書く
  • 不明なCSVを受け取ったとき: 先に文字コードを疑う

CSVの文字化けは、知ってしまえば対策は単純です。次に見るべきポイントは、「このCSVを誰が、どのアプリで、どの手順で開くか」が決まっているかどうかです。そこが曖昧なままでは、UTF-8を選んでもShift_JISを選んでも、同じ事故が繰り返されます。

参照リンク

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次