[解決済み] PythonでBOM付きのUTF-8をBOM無しのUTF-8に変換する。
質問
ここで2つの質問があります。私は、通常 BOM 付きの UTF-8 である一連のファイルを持っています。私はそれらを (理想的にはその場で) BOM 無しの UTF-8 に変換したいと思っています。それは次のように思われます。
codecs.StreamRecoder(stream, encode, decode, Reader, Writer, errors)
がこれを処理するようです。しかし、私は本当に使用上の良い例を見ることはありません。これは、これを処理するための最良の方法でしょうか?
source files:
Tue Jan 17$ file brh-m-157.json
brh-m-157.json: UTF-8 Unicode (with BOM) text
また、異なる入力エンコーディングを明示的に知ることなく扱うことができれば理想的です(ASCIIとUTF-16を参照)。これはすべて実現可能であるべきだと思います。Python の既知のエンコーディングを受け取り、BOM なしで UTF-8 として出力できるソリューションはありますか?
1を編集 は、下からソルンを提案しました(ありがとうございます!)。
fp = open('brh-m-157.json','rw')
s = fp.read()
u = s.decode('utf-8-sig')
s = u.encode('utf-8')
print fp.encoding
fp.write(s)
これだと、以下のようなエラーが出ます。
IOError: [Errno 9] Bad file descriptor
ニュースフラッシュ
コメントで、私が 'r+'/'r+b' ではなく 'rw' モードでファイルを開いたのが間違いだと言われているので、結局私の質問を再編集して解決した部分を削除する必要があります。
どのように解決するのですか?
単純に utf-8-sig" コーデックを使用します。 :
fp = open("file.txt")
s = fp.read()
u = s.decode("utf-8-sig")
これによって
unicode
文字列が得られます。次に
s = u.encode("utf-8")
で通常のUTF-8エンコードされた文字列を取得します。
s
. もしファイルが大きいなら、それらをすべてメモリに読み込むことは避けるべきです。BOM は単にファイルの先頭にある 3 バイトなので、このコードを使ってファイルからそれらを取り除くことができます。
import os, sys, codecs
BUFSIZE = 4096
BOMLEN = len(codecs.BOM_UTF8)
path = sys.argv[1]
with open(path, "r+b") as fp:
chunk = fp.read(BUFSIZE)
if chunk.startswith(codecs.BOM_UTF8):
i = 0
chunk = chunk[BOMLEN:]
while chunk:
fp.seek(i)
fp.write(chunk)
i += len(chunk)
fp.seek(BOMLEN, os.SEEK_CUR)
chunk = fp.read(BUFSIZE)
fp.seek(-BOMLEN, os.SEEK_CUR)
fp.truncate()
ファイルを開き、チャンクを読み込み、読み込んだ場所より3バイト早くファイルに書き出します。ファイルはインプレースで書き直されます。より簡単な解決策は、短いファイルを次のような新しいファイルに書き出すことです。 newtoverの回答 . これはより簡単ですが、短時間で2倍のディスクスペースを使用します。
エンコーディングの推測に関しては、最も特定的なものから最も特定的でないものへとループさせればよいのです。
def decode(s):
for encoding in "utf-8-sig", "utf-16":
try:
return s.decode(encoding)
except UnicodeDecodeError:
continue
return s.decode("latin-1") # will always work
UTF-16でエンコードされたファイルはUTF-8としてデコードされないので、まずUTF-8で試してみます。それが失敗した場合、次に UTF-16 で試します。最後に、Latin-1 を使用します。Latin-1 では 256 バイトすべてが正当な値であるため、これは常に動作します。を返したいかもしれません。
None
なぜなら、これは本当にフォールバックであり、あなたのコードは(可能であれば)より慎重にこれを処理したいと思うかもしれないからです。
関連
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] バイトを文字列に変換する
-
[解決済み] pipでPythonの全パッケージをアップグレードする方法
-
[解決済み] UTF-8とBOMなしUTF-8の違いは何ですか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み] Pythonのマルチプロセッシングプールimap_unorderedの呼び出しの進捗を表示しますか?
-
[解決済み] Django のテストデータベースをメモリ上だけで動作させるには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Pythonのマルチプロセッシングプールimap_unorderedの呼び出しの進捗を表示しますか?
-
[解決済み] Jupyterノートブックでenv変数を設定する方法
-
[解決済み] Spyderを仮想環境で動作させるには?
-
[解決済み] django.db.migrations.exceptions.InconsistentMigrationHistory
-
[解決済み] Pythonの要素別タプル演算(sumなど
-
[解決済み] ファブリック経由でデプロイユーザとしてvirtualenvを有効化する
-
[解決済み] SQLAlchemy - テーブルのリストを取得する
-
[解決済み] Pythonでマルチプロセッシングキューを使うには?
-
[解決済み] subprocess.run()の出力を抑制またはキャプチャするには?
-
[解決済み] Python Logging でログメッセージが2回表示される件