我在python中处理一个非常大的csv文件,其中一些行抛出错误“'utf-8'编解码器无法解码位置7657中的字节0x9b:无效的起始字节”。有没有办法在不手动删除或修复数据的情况下跳过不是utf-8的行?
for filename in filenames:
f = open(filename, 'rt')
reader = csv.reader(f, delimiter = ',')
for row in reader:
#process data for future use
我不能使用非utf8数据,因为以后的进程需要使用utf-8
答案 0 :(得分:1)
您可以使用将行读取为原始字节的过滤器,尝试将其转换为unicode为UTF8,然后:
假设您使用的是Python2,您可以使用以下内容:
class MyFilter:
def __init__(self, instr, errstr):
self.instr = instr
self.errstr = errstr
def __enter__(self):
print("ENTERING filter")
return self
def __exit__(self, a, b, c):
print("EXITING filter")
self.instr.close()
self.errstr.close()
return False
def __next__(self):
line = next(self.instr)
while True:
try:
t = line.decode('utf8')
return line.strip()
except UnicodeDecodeError:
self.errstr.write(line)
line = next(self.instr)
return line
def __iter__(self):
return self
def next(self):
return self.__next__()
然后你可以这样使用它(假设是Python 2.7),在err.txt中获取所有违规行:
with open('file.csv') as istream, open("err.txt", 'w') as err, MyFilter(istream, err) as fd:
c = csv.reader(fd)
for i in c:
# do you stuff, eg: print i
如果使用Python 3,则可以使用几乎相同的过滤器类,只需将行return line.strip()
替换为return t.strip()
,以便返回字符串而不是字节。
用法几乎相同:
with open('file.csv', 'rb') as istream, open("err.txt", 'wb') as err, MyFilter(istream, err) as fd:
c = csv.reader(fd)
for i in c:
# do you stuff, eg: print (i)
根据您的评论,您还希望过滤包含空字符的行。这只需要对过滤器进行轻微更改,while
块变为(Python 3版本):
while True:
if b'\x00' not in line:
try:
t = line.decode('utf8')
return t.strip()
except UnicodeDecodeError:
pass
self.errstr.write(line)
line = next(self.instr)