すべてのリテラルバックスラッシュエスケープシーケンスを翻訳する必要があります。あなたは、正規表現でこれを行うことができます:
import re
seq = re.compile(br'\\[0-8]{3}')
decode_seq = lambda m: bytes([int(m.group()[1:], 8)])
def repair(data):
return seq.sub(decode_seq, data)
これはbytes
オブジェクト内のデータをデコード:
>>> broken = rb"Tom\303\241\305\241 Vala"
>>> repair(broken)
b'Tom\xc3\xa1\xc5\xa1 Vala'
>>> repair(broken).decode('utf8')
'Tomáš Vala'
既存のファイルをラップするために、あなたはあなたのようにバイトを変換するためにio.BufferedIOBase
subclassを実装する必要があると思います読み:
import re
from io import BufferedIOBase
class OctetEscapeDecodeWrapper(BufferedIOBase):
def __init__(self, buffer):
# we wrap a buffer, not a raw object, so don't use raw here.
self._buffer = buffer
self._remainder = b''
def readable(self):
return True
def detach(self):
result, self._buffer = self._buffer, None
return result
def _decode(self, data,
_seq=re.compile(br'\\[0-8]{3}'),
_decode=lambda m: bytes([int(m.group()[1:], 8)])):
return _seq.sub(_decode, data)
def read1(self, size=-1):
self._remainder, data = b'', self._remainder + self._buffer.read1(size)
trail = data.rfind(b'\\', -3)
if trail > -1 and all(48 <= data[i] <= 57 for i in range(trail + 1, len(data))):
# data ends \dd or \d, retain until next read so we can decode then
self._remainder, data = data[trail:], data[:trail]
return self._decode(data)
read = read1
def readinto1(self, b):
data = self.read1(len(b))
b[:len(data)] = data
return len(data)
readinto = readinto1
これは、その場で自分のデータを復号化するために、既存のバイナリファイルをラップするために使用することができます。
import csv
from io import TextIOWrapper
with open(path_to_file, 'rb') as binary:
text = TextIOWrapper(OctetEscapeDecodeWrapper(binary), encoding='utf8')
reader = csv.reader(text)
for row in reader:
# ...
デモ:*は `\ ddd`配列を含む
>>> from io import BytesIO, TextIOWrapper
>>> sample = BytesIO(b'Tom\303\241\305\241 Vala, V\303\241lec, 1.1.1984,')
>>> b = OctetEscapeDecodeWrapper(sample)
>>> t = TextIOWrapper(b, encoding='utf8')
>>> import csv
>>> next(csv.reader(t))
['Tomáš Vala', ' Válec', ' 1.1.1984', '']
あなた*実際のデータ?それは文字通りのバックスラッシュと3桁です。これはPythonの文字列リテラルで '\ ddd'を使うのと同じことではありません。代わりにあなたの実際のデータのサンプルを与えることができますか? –
あなたのデータは 'r" Tom \ 303 \ 241 \ 305 \ 241 Vala "'としてPython文字列リテラルで定義することができ、先頭に 'r'を付けたり、バックスラッシュを倍にしたりすることができます。 –
ファイルには、 Tom \ 303 \ 241 \ 305 \ 241 Vala、V \ 303 \ 241lec、1.1.1984、 – Panther