我正在尝试获取包含奇数字符的 Unicode 文件流,并使用流读取器将其包装,将其转换为 Ascii,忽略或替换所有无法编码的字符。
我的流看起来像:
"EventId","Rate","Attribute1","Attribute2","(。・ω・。)ノ"
...
我尝试动态更改流的尝试如下所示:
import chardet, io, codecs
with open(self.csv_path, 'rb') as rawdata:
detected = chardet.detect(rawdata.read(1000))
detectedEncoding = detected['encoding']
with io.open(self.csv_path, 'r', encoding=detectedEncoding) as csv_file:
csv_ascii_stream = codecs.getreader('ascii')(csv_file, errors='ignore')
log( csv_ascii_stream.read() )
log
行的结果是: UnicodeEncodeError: 'ascii' codec can't Encodecharacters inposition 36-40: ordinal not in range(128)
Even尽管我使用 errors='ignore'
我希望生成的流(读取时)如下所示:
"EventId","Rate","Attribute1","Attribute2","(?????)?"
...
或者,"EventId","Rate","Attribute1","Attribute2","()"
(使用 'ignore'
而不是 '替换'
)
为什么会发生异常?
我见过很多解码字符串的问题/解决方案,但我的挑战是在读取流时更改流(使用 .next()
),因为文件可能太大使用 .read()
最佳答案
您混淆了编码和解码端。
对于解码,你做得很好。您将其作为二进制数据打开,chardet
第一个 1K,然后使用检测到的编码以文本模式重新打开。
但随后您尝试使用 codecs.getreader
将已解码的数据进一步解码为 ASCII 。该函数返回 StreamReader
,它从流中解码数据。那是行不通的。您需要将该数据编码为 ASCII。
但是,当您只想对单个文本 block 进行编码时,尚不清楚为什么您首先要使用 codecs
流解码器或编码器一次性完成,这样您就可以记录它。为什么不直接调用 encode
方法呢?
log(csv_file.read().encode('ascii', 'ignore'))
如果你想要一些可以用作行的惰性迭代的东西,你可以构建一些完全通用的东西,但是做像UTF8Recorder
这样的事情要简单得多> csv
中的示例文档:
class AsciiRecoder:
def __init__(self, f, encoding):
self.reader = codecs.getreader(encoding)(f)
def __iter__(self):
return self
def next(self):
return self.reader.next().encode("ascii", "ignore")
或者,更简单地说:
with io.open(self.csv_path, 'r', encoding=detectedEncoding) as csv_file:
csv_ascii_stream = (line.encode('ascii', 'ignore') for line in csv_file)
关于python - 将 Unicode 流重新编码为 Ascii 忽略错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26307271/