質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.87%

PythonでXMLファイルの文字コード変換中にUnicodeDecodeErrorが出る

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 941

sera_sera

score 10

 前提・実現したいこと

卒業研究でPythonでアプリを作っているPython初心者です。
実現したいこととしまして、対象ディレクトリ(drive)下から拡張子xmlのファイルを全てUTF8に変換して選択したディレクトリに新規保存したいです。

 発生している問題・エラーメッセージ

C:\Users\sera\PycharmProjects\PatentApp
C:\Users\sera\PycharmProjects\save
operation_start

C:\Users\sera\PycharmProjects\PatentApp\translate\2013523997.xml
C:\Users\sera\PycharmProjects\save\2013523997.xml
Traceback (most recent call last):
  File "C:\Users\sera\PycharmProjects\PatentApp\patentApp\copyXMLfiles.py", line 37, in <module>
    for row in ff: # 元ファイルから1行ずつ読みだして
  File "C:\Program Files\Python37\lib\codecs.py", line 712, in __next__
    return next(self.reader)
  File "C:\Program Files\Python37\lib\codecs.py", line 643, in __next__
    line = self.readline()
UnicodeDecodeError: 'euc_jp' codec can't decode byte 0xbf in position 2: illegal multibyte sequence
[Finished in 0.221s]

 該当のソースコード

import sys # sysモジュール読み込み
import glob # globモジュール読み込み
import os # osモジュール読み込み
import codecs # codecsモジュールの読み込み

#sys.stdout = codecs.getwriter('utf_8')(sys.stdout)
drive = r"C:\Users\sera\PycharmProjects\PatentApp"
print(drive) # 確認用
save = r"C:\Users\sera\PycharmProjects\save"
print(save) # 確認用
print("operation_start\n")

os.chdir(drive) # カレントディレクトリを走査対象に移動
path_list = glob.glob('**/*.xml', recursive=True) # 拡張子.xmlを網羅,リストに格納

for x in path_list: # 拡張子.xml格納リストを網羅表示
    fromdir = drive + '\\' + x # 操作対象絶対パス
    print(fromdir) # ↑の表示(確認用)
    y = os.path.basename(fromdir) # 操作対象のファイル名取得
    todir = save + '\\' + y # 保存先ディレクトリの絶対パス
    print(todir) # ↑の表示(確認用)
    # ↓ 変換&新規出力
    ff = codecs.open(fromdir, 'r', encoding='euc-jp') # 元ファイルを読み込み
    fout_utf = open(todir, 'w', encoding='utf-8') # UTFでの新ファイルを新規作成
    for row in ff: # 元ファイルから1行ずつ読みだして
        fout_utf.write(row) # コピー先新ファイルに書き出す
    ff.close() # ffを閉じる
    fout_utf.close() # fout_utfを閉じる
print("end")

 試したこと

・#sys.stdout = codecs.getwriter('utf_8')(sys.stdout)の削除
・encoding='euc-jp'をencoding='utf-8'に書き換え

 補足情報(FW/ツールのバージョンなど)

バージョン:Python3.7
開発環境:Atom1.31.2
こちらのサイトを参考にしました↓
https://www.python-izm.com/advanced/file_rw/

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Python3.7を使っているのに、python2系のコードを参考にしているっぽいのはいかがなものでしょうか。

文字コードは、エラーから察するにBOM付きUTF-8ではないでしょうか。encoding='utf_8_sig'を試してみてください。

 追記

Traceback (most recent call last):
  File "C:\Users\sera\PycharmProjects\PatentApp\patentApp\copyXMLfiles.py", line 37, in <module>
    for row in ff: # 元ファイルから1行ずつ読みだして
  File "C:\Program Files\Python37\lib\codecs.py", line 712, in __next__
    return next(self.reader)
  File "C:\Program Files\Python37\lib\codecs.py", line 643, in __next__
    line = self.readline()
UnicodeDecodeError: 'euc_jp' codec can't decode byte 0xbf in position 2: illegal multibyte sequence
[Finished in 0.221s]

なので、ff(読み込み側ファイル)が想定している文字コードと違うことは確実です。ヒントは「byte 0xbf in position 2」で、3バイト目(0から数えるから)に0xbfがあるということですから、BOMつきUTF-8のBOM「0xEF 0xBB 0xBF」を拾っている可能性が濃厚……ということです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/17 17:00

    sjisだったか。BOMっぽく見えたのはまぐれでしたね。しかし、<?xml version="1.0" encoding="EUC-JP"?>でSJISなのはなぜ・・・

    キャンセル

  • 2018/10/17 17:05

    変換後のファイルの中身も確認してみましたが、やはり一行目はencoding='EUC-JP'?となっていましたね…。変換前も後も同じですがnkf32ではしっかりUTF-8となっているので大丈夫だとは思いますが…。

    キャンセル

  • 2018/10/17 17:07

    とにかく解決本当にありがとうございました!
    これで研究を進める事ができますm(__)m

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.87%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる