C
Python検証済み

Error UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte の原因と直し方【Dockerで検証済み】

Error UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: in… の原因と解決方法。検証済みの解決コマンド付きで、現象→原因→解決→確認の順に最短で直せます。

発生したエラー

エラー出力
Error UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

結論:まずこれで直ります

下の解決コマンドを順に実行すれば直ります。

解決コマンド
cat > /tmp/fix_unicode.py << 'EOF'
import chardet

# まず実際のエンコーディングを検出する
with open('/tmp/test_utf16.txt', 'rb') as f:
    raw = f.read()

detected = chardet.detect(raw)
print(f'検出されたエンコーディング: {detected}')
encoding = detected['encoding']

# 検出したエンコーディングで正しく読み込む
with open('/tmp/test_utf16.txt', 'r', encoding=encoding) as f:
    content = f.read()
    print(f'読み込み成功: {content}')

# 必要であればUTF-8として保存し直す
with open('/tmp/test_utf16_fixed.txt', 'w', encoding='utf-8') as f:
    f.write(content)
print('UTF-8ファイルとして保存完了')
EOF
pip install chardet -q
python /tmp/fix_unicode.py

現象どんなエラーか

次の操作を行うと(検証環境: python:3.11)、上記のエラーが発生します。まずは下の再現コマンドで、同じ状況を再現できることを確認してください。

検証環境:python:3.11

再現コマンド
cat > /tmp/reproduce_unicode.py << 'EOF'
# UTF-16 LE BOM (0xFF 0xFE) で始まるバイト列をUTF-8として読もうとする
with open('/tmp/test_utf16.txt', 'wb') as f:
    f.write(b'\xff\xfe' + 'こんにちは'.encode('utf-16-le'))

# UTF-8として開こうとするとエラーになる
with open('/tmp/test_utf16.txt', 'r', encoding='utf-8') as f:
    content = f.read()
    print(content)
EOF
python /tmp/reproduce_unicode.py

原因なぜ起きるのか

このエラーは、UTF-8以外のエンコーディング(UTF-16やShift_JIS、Latin-1など)で書かれたファイルを、Pythonがデフォルトのencoding='utf-8'で読み込もうとしたときに発生します。0xFFはUTF-8の有効な先頭バイトではなく、UTF-16のBOM(Byte Order Mark: 0xFF 0xFE)や他のエンコーディング固有のバイトです。 根本的な解決策は、ファイルの実際のエンコーディングを正しく特定し、それを指定して開くことです。方法は以下の通りです: 1. chardetやcharsetaliasライブラリを使ってエンコーディングを自動検出する。 2. ファイルの出所や作成環境からエンコーディングを確認し、open()のencodingパラメータに明示する(例: encoding='utf-16', encoding='shift_jis'など)。 3. エンコーディングが不明で多様なファイルを扱う場合はerrors='replace'やerrors='ignore'も一手ですが、文字化けの原因になるため、根本解決としてはエンコーディング特定が優先です。 4. 長期的にはファイルをUTF-8に統一して保存し直すことで、以降は問題が起きなくなります。

解決解決手順

修正コマンド
cat > /tmp/fix_unicode.py << 'EOF'
import chardet

# まず実際のエンコーディングを検出する
with open('/tmp/test_utf16.txt', 'rb') as f:
    raw = f.read()

detected = chardet.detect(raw)
print(f'検出されたエンコーディング: {detected}')
encoding = detected['encoding']

# 検出したエンコーディングで正しく読み込む
with open('/tmp/test_utf16.txt', 'r', encoding=encoding) as f:
    content = f.read()
    print(f'読み込み成功: {content}')

# 必要であればUTF-8として保存し直す
with open('/tmp/test_utf16_fixed.txt', 'w', encoding='utf-8') as f:
    f.write(content)
print('UTF-8ファイルとして保存完了')
EOF
pip install chardet -q
python /tmp/fix_unicode.py

確認直ったか確認する

確認コマンド
python -c "
import chardet
with open('/tmp/test_utf16_fixed.txt', 'rb') as f:
    raw = f.read()
detected = chardet.detect(raw)
print('エンコーディング:', detected)
with open('/tmp/test_utf16_fixed.txt', 'r', encoding='utf-8') as f:
    content = f.read()
print('内容:', content)
assert 'こんにちは' in content, 'テキスト不一致'
print('検証成功')
"

動画で見る

この記事の解決手順は実環境で検証しています

山田 英紀(社内SE 5年以上・13業種以上の業務システムを開発/運用)が、 掲載コマンドを検証環境で実行し、再現〜解決〜確認まで通ることを確認しています。

この手順でも直らない・自社の環境で再現する場合

エラー調査・修正から、業務システムの改善までご相談いただけます。

無料で相談する

関連する記事