文字コードと安全なファイル確認|PC・ブラウザ・ファイルの基本

このページはプロモーション(広告)を含みます。

PC・ブラウザ・ファイルの基本(初級・読む25分+演習30分)

この授業のゴール

仕事でどう使うか

データの仕事では、他人が作ったファイルを毎日のように開きます。文字化けしたまま分析すると、カテゴリ名が壊れて集計が合いません。出所の分からないファイルを開くと、情報漏えいやウイルス感染の入口になります。

路線 この授業の使いどころ
DS(データサイエンティスト) 取引先や他部署のCSVを読み込む前に、文字コードと列数を確認する。読み間違えた列名や値のまま集計しない
ML(機械学習エンジニア) 学習データのカテゴリ名やテキストが壊れていないか確認する。文字化けしたラベルは、別のクラスとして学習される
DX(DX推進・AI企画) 業務システムの入出力ファイルの文字コード・改行・区切り文字を仕様に書く。ファイル受け渡しの安全ルールを決める
RS(研究者) 共同研究者から受け取るデータの出所と形式を記録する。再現性のために文字コードも記録に残す

この授業の判定ポイントは、拡張子だけで形式を信じないことと、開く前に確認することです。

前提

前提は、ファイル・フォルダ・拡張子 の拡張子と先頭バイトの考え方、保存・ダウンロード・アップロード の「文字数とバイト数は別の量」です。

この授業では、実行ファイルを開く練習はしません。教材のCSV(架空データ)だけを使います。

身近な状況:開いたら「縺ゅ>縺…」だらけ

Fさんは、他部署から届いたCSVを開きました。ところが、列名が 譛磯。� のような記号の羅列になっていました。壊れたのではなく、読み方を間違えているだけです。

もう1つの場面です。Fさんのメールに、請求書.pdf.exe という添付ファイルが届きました。画面の設定で拡張子が非表示なら、請求書.pdf に見えます。

この2つは、どちらも「名前や見た目と、中身の読み方がずれる」という同じ種類の問題です。

場面 起きていること 対処
文字化け ファイルが書かれた文字コードと、読むときの文字コードが違う 正しい文字コードで読み直す。化けたまま保存しない
二重拡張子 最後の拡張子が実行ファイルを示すのに、前の部分でPDFに見せている 最後の拡張子で判断し、開かない

この授業では、ファイルを開く前に確認する手順と、開いた後に中身を確かめる手順を身につけます。

直感的な説明:文字と番号の対応表

コンピューターは文字を直接しまえません。文字に番号を振り、その番号をバイト列にして保存します。このとき、どの番号表・どの変換規則を使うかが文字コード(エンコーディング)です。

たとえるなら、暗号の本です。書く人がA社の暗号本で書いた文を、読む人がB社の暗号本で読むと、意味の違う文字になります。バイト列は同じでも、読む規則が違えば別の文字になります。

日本語のCSVでよく出会う規則は2つです。

たとえの限界:文字コードは暗号ではなく公開された規則です。ただし、ファイルの中に「この規則で書いた」という印が必ず入っているわけではなく、読む側が推測することが多い点が、問題の原因です。

正確な定義:Unicode、エンコーディング、BOM、改行

Unicode は、世界中の文字に番号(コードポイント)を振った規格です。UTF-8 は、その番号を1〜4バイトで保存する方式(エンコーディング)の1つです。

用語 意味
エンコード(encode) 文字列(str)→ バイト列(bytes)。s.encode("utf-8")
デコード(decode) バイト列 → 文字列。b.decode("utf-8")。規則が合わないとエラーか文字化け
BOM(Byte Order Mark) UTF-8ファイルの先頭に付く3バイト EF BB BF。Excelなどが「UTF-8だ」と判断する目印に使う
改行コード 行の区切り。\n(LF)が主流、Windowsでは \r\n(CRLF)もある

Pythonでのutf-8-sigは、BOMがあれば除いて読み、なければそのまま読むデコード方式です。

同じ日本語を2つの規則でエンコードし、バイト数を比べます。

s = "こんにちは"
print(len(s))
print(len(s.encode("utf-8")), len(s.encode("cp932")))
b = s.encode("utf-8")
print(b.decode("cp932"))

出力は、5(文字数)、15 10(UTF-8は15バイト、CP932は10バイト)、そして 縺薙s縺ォ縺。縺ッ です。UTF-8で書いたバイト列をCP932で読むと、エラーにならずに文字化けします。エラーが出ない文字化けがあるので、「読めた」だけでは正しさの確認になりません。

段階付き例題:教材CSVを開く前と開いた後に確認する

問題:教材の churn.csv(解約データ。架空)を、安全に確認して読み込む。

ステップ1:出所を確認する。この教材に内蔵された架空データなので、出所は明確です。実務では「誰が・いつ・どの経路で」送ったかを確認し、不明なら開きません。

ステップ2:名前と拡張子。churn.csv は最後の拡張子が csv で、二重拡張子ではありません。ただし、これだけでは形式を保証しません。

ステップ3:サイズ。極端に大きい、または小さいときは疑います。

ステップ4:先頭バイト。BOMの有無、実行ファイルやZIPの目印がないかを確認します。

ステップ5:先頭の数行を読んで、列数をそろえて確認する。

from collections import Counter
raw = open("/data/churn.csv", "rb").read()
print(len(raw), raw[:3] == b"\xef\xbb\xbf")
text = raw.decode("utf-8")
lines = text.splitlines()
print(len(lines))
print(lines[1])
print(Counter(len(l.split(",")) for l in lines))
try:
    raw.decode("cp932")
except UnicodeDecodeError as e:
    print("cp932では読めない:", type(e).__name__)

出力は、158657 False(バイト数、BOMなし)、3001(ヘッダー1行+3000行)、1,56,2980,0,14.7,月額,東日本,50代以上,,0,train、Counter({11: 3001})(全行が11列)、cp932では読めない: UnicodeDecodeError です。

ステップ6:意味を言葉にする。このファイルはUTF-8として読め、全行の列数が一致します。CP932で読むと、エラーが出ました。どの文字コードで読めたかを記録に残します。なお、行によっては列数が違う場合、カンマを含む値が引用符で囲まれている可能性があるので、pandas.read_csv のような専用の道具で読む場合も、行数と列数の確認は欠かせません。

操作して理解する:読む規則を変えて、結果を見る

次のコードで、日本語を2つの規則で書き、読む規則をそろえた場合・食い違わせた場合を比べます。

word = "売上"
u = word.encode("utf-8")
c = word.encode("cp932")
print(u, c)

def try_decode(b, enc):
    try:
        return b.decode(enc)
    except UnicodeDecodeError:
        return "(エラー)"

for name, b in (("UTF-8で書いた", u), ("CP932で書いた", c)):
    print(name, try_decode(b, "utf-8"), try_decode(b, "cp932"))

出力は、b'\xe5\xa3\xb2\xe4\xb8\x8a' b'\x94\x84\x8f\xe3'、UTF-8で書いた 売上 (エラー)、CP932で書いた (エラー) 売上 です。1行目のバイト列は左がUTF-8(6バイト)、右がCP932(4バイト)です。

注目点は2つです。(1) 書いた規則で読めば正しく読め、違う規則で読むと、この例ではエラーになります。(2) 前の節の こんにちは は、UTF-8で書いたものをCP932で読んでもエラーにならず文字化けしました。同じ「規則の食い違い」でも、エラーになるかどうかはバイト列の並びで決まります。エラーの有無だけで判断せず、読んだ結果を目で見ることが必要です。

実務では、次の順で試すのが定石です。

  1. utf-8-sig(BOMの有無どちらにも対応)で読む。
  2. 失敗したら cp932 で読む。
  3. 読めた結果の先頭数行を目で見て、日本語が正しいことを確かめる。

試してみる:word を "こんにちは" や "ABC" に変えて、バイト数と読み方の結果がどう変わるか確かめましょう。半角英数字はUTF-8でもCP932でも1文字1バイトで、同じバイト列になります。

発展:自動判定の限界と、ファイルの危険度

文字コードの自動判定は推定です。バイト列の並びの統計から「たぶんこの規則」と当てるもので、短いファイルや、特定の文字だけのファイルでは外れます。外れたときは、読んだ結果を目で見て気付くしかありません。

拡張子ごとの危険度の目安(一般的な考え方):

分類 拡張子の例 扱い
データ(テキスト) .csv、.txt、.json 実行されない。ただし中身の確認は必要
文書・表計算 .pdf、.xlsx、.docx 通常は安全だが、マクロ入り(.xlsm、.docm)は実行機能を持つ
圧縮 .zip、.gz 展開してから、中身の名前と拡張子を確認する
実行ファイル・スクリプト .exe、.bat、.cmd、.js、.vbs、.scr、.ps1、.msi、.jar データとして届いたら開かない

二重拡張子(請求書.pdf.exe)では、最後の拡張子が実際の種類を決めます。OSの設定で拡張子を表示しておくことが、最初の防御です。

出所が不明、緊急を装う、パスワード付きZIPで届く、といった特徴はよくある手口です。判断に迷うときは、開かずに、情報システム部門などの担当者に相談します。セキュリティの扱いは組織のルールが優先です。この説明は執筆時点(2026年)の一般的なもので、最新は組織や公的機関の案内で確認してください。

CSVの区切り文字・引用符にも例外があります。値にカンマを含む場合、"東京,23区" のように引用符で囲みます。単純な split(",") では列がずれるため、実務では専用の読み込み関数(csv モジュールや pandas)を使います。

よくある失敗

失敗1:化けた文字をそのまま保存し直して、原本を壊す

誤った操作:文字化けしたCSVを、そのまま「保存」した。

original = "売上".encode("utf-8")
garbled = original.decode("cp932", errors="replace")
saved = garbled.encode("utf-8")
print(garbled, saved)
print(saved == original)

出力は 螢イ荳� b'\xe8\x9e\xa2\xef\xbd\xb2\xe8\x8d\xb3\xef\xbf\xbd' と False です。化けた文字を保存すると、元のバイト列に戻せなくなります。特に、errors="replace" で置換した文字(�)は、元の情報が失われます。

直し方:文字化けしたら、保存せず、読み込む文字コードを変えて読み直す。原本は別に残し、作業用コピーで試す(ファイル・フォルダ・拡張子)。

失敗2:拡張子の見た目で、安全なPDFだと思い込む

誤った判断:請求書.pdf.exe が画面で 請求書.pdf に見えたので、PDFだと思って開いた。

from pathlib import PurePosixPath
name = "請求書.pdf.exe"
p = PurePosixPath(name)
print("見かけ:", p.stem)
print("最後の拡張子:", p.suffix)
print(p.suffixes)

出力は 見かけ: 請求書.pdf、最後の拡張子: .exe、['.pdf', '.exe'] です。実際の種類は最後の .exe で、実行ファイルです。

直し方:OSの設定で拡張子を表示し、最後の拡張子で判断する。実行ファイルがデータとして届いたら開かず、担当者に報告する。

失敗3:文字数とバイト数を取り違える

誤った判断:「入力欄の上限は20バイト。メモは9文字だから入る。」

name = "山田太郎の注文メモ"
print(len(name))
print(len(name.encode("utf-8")))
print(len(name.encode("cp932")))

出力は 9(文字数)、27(UTF-8のバイト数)、18(CP932のバイト数)です。上限20バイトに対して、UTF-8では27バイトで入らず、CP932では18バイトで入ります。上限が文字数かバイト数か、どの文字コードのバイトかで、入る・入らないが変わります。

直し方:仕様に「文字数」か「バイト数」かを書く。バイトで数えるなら、文字コードも書く。確認は len(s) と len(s.encode(...)) の両方で行います。

まとめ

用語

文字コード(character encoding)

文字を番号とバイト列に対応づける規則。UTF-8やCP932などがある。

UTF-8(UTF-8)

Unicodeの文字を1〜4バイトで表す標準的な方式。日本語は通常3バイト。

CP932(CP932 (Windows-31J))

Shift_JISにWindows独自の文字を加えた日本語の文字コード。日本語は通常2バイト。

BOM(Byte Order Mark)

UTF-8ファイルの先頭に付くことがある3バイトの目印。utf-8-sig で読むと除かれる。

二重拡張子(double extension)

請求書.pdf.exe のように拡張子が2つ以上続く名前。実際の種類は最後の拡張子で決まる。

よくある質問

なぜ文字コードが複数あるのですか?

コンピューターの歴史の中で、国や会社ごとに別々の規則が作られたからです。日本語だけでもCP932やEUC-JPなどがあります。現在は世界共通のUnicodeとUTF-8が標準で、新しいシステムの多くはUTF-8を使います。

ExcelでCSVを開くと文字化けするのはなぜですか?

ExcelがBOMのないUTF-8を、CP932として読むことがあるからです。BOM付きUTF-8で保存するか、Excelの「データの取り込み」機能で文字コードを指定すると読めます。環境や版によって動作が異なるので、実際の画面で確認してください。

文字コードを自動判定するライブラリがあれば、確認は不要ですか?

不要にはなりません。自動判定は推定なので、外れることがあります。読んだ結果の先頭数行を目で見て確かめる手順は残します。判定結果が間違っても、気付ける仕組みを持つことが大切です。

CSVの列数が行によって違うのは、何が原因ですか?

値にカンマや改行が含まれ、引用符で囲まれている場合に、単純なsplit(',')で数えると列数がずれて見えます。また、データ自体の欠落や、手作業の編集ミスも原因になります。専用の読み込み関数で読み、行数・列数を確認します。

ウイルス対策ソフトがあれば、開く前の確認は不要ですか?

不要にはなりません。対策ソフトは多くの脅威を検出しますが、全てではありません。出所と拡張子の確認は、自分でできる最初の防御です。ソフトの検査と、人の確認を重ねます。

個人情報を含むCSVを受け取ったときは、どうしますか?

社内のルールに従って保管し、必要な範囲の人だけが見られるようにします。受け取った事実、保存先、削除期限を記録に残します。この教材のデータは全て架空ですが、実務では最初にルールを確認してください。

確認問題

問1 UTF-8で保存されたCSVを、CP932として読むと起こりやすいことはどれか。

  1. ① 必ずエラーで止まる
  2. ② エラーにならず文字化けすることも、エラーになることもある
  3. ③ 自動的に正しい日本語になる
  4. ④ ファイルが削除される
解答と解説

正解:②

バイト列の並びによって、不正なバイトが出てエラーになる場合と、別の文字として読めて文字化けする場合があります。

問2 「こんにちは」(5文字)をUTF-8とCP932でバイト列にしたときのバイト数の組み合わせは。

  1. ① UTF-8:5、CP932:5
  2. ② UTF-8:10、CP932:15
  3. ③ UTF-8:15、CP932:15
  4. ④ UTF-8:15、CP932:10
解答と解説

正解:④

UTF-8では日本語1文字が通常3バイト、CP932では2バイトなので、5文字は15バイトと10バイトです。

問3 請求書.pdf.exe というファイルが届いた。この実際の種類として最も適切なのはどれか。

  1. ① 実行ファイル
  2. ② PDFファイル
  3. ③ 文字コードがPDFの画像
  4. ④ ZIPファイル
解答と解説

正解:①

拡張子は最後の . 以降で決まります。最後の .exe が実際の種類で、PDFに見せかけた実行ファイルの可能性があります。

問4 UTF-8のBOM付きファイルを utf-8(BOMを除かない)で読むと、起こりうることはどれか。

  1. ① ファイルが読めずエラーになる
  2. ② 全ての日本語が文字化けする
  3. ③ 1行目の最初の列名の前に、見えない文字 \ufeff が付く
  4. ④ BOMは読み込みに一切影響しない
解答と解説

正解:③

BOMは先頭の3バイトで、utf-8 で読むとコードポイント \ufeff として残ります。utf-8-sig なら除かれます。

問5 文字化けしたCSVを見つけた。最初にすべきことはどれか。

  1. ① そのまま上書き保存して、後で直す
  2. ② 文字を手で打ち直す
  3. ③ ファイルを削除して作り直す
  4. ④ 保存せずに、読み込む文字コードを変えて読み直す
解答と解説

正解:④

化けた文字を保存すると、元のバイト列に戻せなくなります。読み方を変えれば、原本は変えずに直せます。

問6 知らない相手から届いたZIPの中に data.csv が入っていた。開く前の対応として最も適切なのはどれか。

  1. ① CSVはデータなので、そのまま開いてよい
  2. ② 出所を確認できるまで開かず、必要なら担当者に相談する
  3. ③ 拡張子を .xlsx に変えてから開く
  4. ④ ZIPごと別の人に転送する
解答と解説

正解:②

拡張子が .csv でも、中身や出所は保証されません。出所が不明なファイルは、確認が取れるまで開かないのが基本です。

次に学ぶこと

次は エラー時の切り分けとバックアップ で、エラーが出たときの切り分けと、バックアップを学びます。ここまでの確認手順を使って、統合演習(CSVを読み込み、ノートと結果を出力して再読込する)を行います。

この授業の確認問題だけでモジュールの習得とはしません。ON01 の総合テストと、CSVを使った自力課題で判定します。データの1行が何を表すかは 行と列と1行の単位 で扱います。

キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。

アプリを無料で開く有料版と無料版の違い