通过 Python 修改非文本文件 3
Modifying non-text files via Python 3
我正在开发一个 encryption/decryption 程序,我让它可以处理文本文件;但是,我无法打开任何其他格式。例如,如果我这样做:
a_file = open('C:\Images\image.png', 'r', encoding='utf-8')
for a_line in a_file:
print(a_line)
我得到:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\WinPython-64bit-3.4.3.4\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 685, in runfile
execfile(filename, namespace)
File "C:\WinPython-64bit-3.4.3.4\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 85, in execfile
exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)
File "C:/Comp_Sci/Coding/line_read_test.py", line 2, in <module>
for a_line in a_file:
File "C:\WinPython-64bit-3.4.3.4\python-3.4.3.amd64\lib\codecs.py", line 319, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte
我做错了什么?
您将其作为文本文件打开,并假设您可以读取行并从中有意义地打印任何内容。
with open(r'C:\Images\image.png', 'rb') as a_file:
while True:
data = a_file.read(32)
if not data:
break
print(data)
简短版本:您正在以文本模式打开二进制文件。使用 'rb'
而不是 'r'
(并删除 encoding
参数),你会做对的。
长版:Python 3 在bytestrings和Unicode字符串之间做了非常严格的区分。 str
类型只包含个Unicode字符串; str
的每个字符都是一个 Unicode 代码点。另一方面,bytes
类型表示一系列不一定对应于文本的 8 位值。例如,.PNG 文件应作为 bytes
对象而不是 str
对象加载。通过将 encoding="utf-8"
参数传递给 open()
,您告诉 Python 您的文件仅包含有效的 UTF-8 文本,而 .PNG 显然不是。相反,您应该使用 'rb'
将文件作为二进制文件打开,而不是使用任何编码。那么当你读取文件时你会得到 bytes
个对象而不是 str
个对象,你需要区别对待它们。
我看到 @ignacio-vazquez-abrams 在我输入这个答案时已经发布了很好的示例代码,所以我不会重复他的工作。他的代码是正确的:使用它,你会没事的。
我正在开发一个 encryption/decryption 程序,我让它可以处理文本文件;但是,我无法打开任何其他格式。例如,如果我这样做:
a_file = open('C:\Images\image.png', 'r', encoding='utf-8')
for a_line in a_file:
print(a_line)
我得到:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\WinPython-64bit-3.4.3.4\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 685, in runfile
execfile(filename, namespace)
File "C:\WinPython-64bit-3.4.3.4\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 85, in execfile
exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)
File "C:/Comp_Sci/Coding/line_read_test.py", line 2, in <module>
for a_line in a_file:
File "C:\WinPython-64bit-3.4.3.4\python-3.4.3.amd64\lib\codecs.py", line 319, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte
我做错了什么?
您将其作为文本文件打开,并假设您可以读取行并从中有意义地打印任何内容。
with open(r'C:\Images\image.png', 'rb') as a_file:
while True:
data = a_file.read(32)
if not data:
break
print(data)
简短版本:您正在以文本模式打开二进制文件。使用 'rb'
而不是 'r'
(并删除 encoding
参数),你会做对的。
长版:Python 3 在bytestrings和Unicode字符串之间做了非常严格的区分。 str
类型只包含个Unicode字符串; str
的每个字符都是一个 Unicode 代码点。另一方面,bytes
类型表示一系列不一定对应于文本的 8 位值。例如,.PNG 文件应作为 bytes
对象而不是 str
对象加载。通过将 encoding="utf-8"
参数传递给 open()
,您告诉 Python 您的文件仅包含有效的 UTF-8 文本,而 .PNG 显然不是。相反,您应该使用 'rb'
将文件作为二进制文件打开,而不是使用任何编码。那么当你读取文件时你会得到 bytes
个对象而不是 str
个对象,你需要区别对待它们。
我看到 @ignacio-vazquez-abrams 在我输入这个答案时已经发布了很好的示例代码,所以我不会重复他的工作。他的代码是正确的:使用它,你会没事的。