我正在尝试将文本文件读入python,但它似乎使用了一些非常奇怪的编码。我试着平常:
file = open('data.txt','r')
lines = file.readlines()
for line in lines[0:1]:
print line,
print line.split()
输出:
0.0200197 1.97691e-005
['0\x00.\x000\x002\x000\x000\x001\x009\x007\x00', '\x001\x00.\x009\x007\x006\x009\x001\x00e\x00-\x000\x000\x005\x00']
打印线条工作正常,但在我尝试拆分线以便将其转换为浮动之后,它看起来很疯狂。当然,当我尝试将这些字符串转换为浮点数时,会产生错误。有关如何将这些转换为数字的任何想法?
如果您想尝试加载它,我会将示例数据文件放在此处: https://dl.dropboxusercontent.com/u/3816350/Posts/data.txt
我想简单地使用numpy.loadtxt或numpy.genfromtxt,但他们也不想处理这个疯狂的文件。
答案 0 :(得分:14)
我愿意打赌这是一个UTF-16-LE文件,无论你的默认编码是什么,你都在阅读它。
在UTF-16中,每个字符占用两个字节。*如果您的字符都是ASCII,这意味着UTF-16编码看起来像ASCII编码,每个字符后加一个'\ x00'。
要解决此问题,只需解码数据:
print line.decode('utf-16-le').split()
或者使用io或codecs模块在文件级别执行相同的操作:
file = io.open('data.txt','r', encoding='utf-16-le')
*这有点过于简单化:每个BMP字符占用两个字节;每个非BMP字符都变成代理对,两个代理中的每一个都占用两个字节。但你可能并不关心这些细节。
答案 1 :(得分:2)
对我来说看起来像UTF-16。
>>> test_utf16 = '0\x00.\x000\x002\x000\x000\x001\x009\x007\x00'
>>> test_utf16.decode('utf-16')
u'0.0200197'
您可以直接使用Unicode字符串:
>>> float(test_utf16)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: null byte in argument for float()
>>> float(test_utf16.decode('utf-16'))
0.020019700000000001
如果您愿意,可以将它们编码为不同的东西:
>>> float(test_utf16.decode('utf-16').encode('ascii'))
0.020019700000000001
请注意,您需要在处理过程中尽早执行此操作。正如您的评论所指出的,split
在utf-16编码表单上的行为不正确。空格字符' '
的utf-16表示形式为' \x00'
,因此split
删除空格但留下空字节。
2.6和更高版本的io
库可以为您处理此问题,旧的codecs
库也可以。 io
可以更好地处理换行符,因此如果可用的话,它会更好。
答案 2 :(得分:1)
这实际上只是@ abarnert的建议,但我想将其作为答案发布,因为这是最简单的解决方案,也是我最终使用的解决方案:
file = io.open(filename,'r',encoding='utf-16-le')
data = np.loadtxt(file,skiprows=8)
这演示了如何使用io.open创建文件对象,使用您的文件碰巧具有的任何疯狂编码,然后将该文件对象传递给np.loadtxt(或np.genfromtxt)以便快速轻松地加载。
答案 3 :(得分:0)
这段代码将做必要的
file_handle=open(file_name,'rb')
file_first_line=file_handle.readline()
file_handle.close()
print file_first_line
if '\x00' in file_first_line:
file_first_line=file_first_line.replace('\x00','')
print file_first_line
当您尝试在替换之前使用'file_first_line.split()'时,输出将包含'\ x00'我只是尝试将'\ x00'替换为空并且它有效。