如何在Python 3中将字节写入文件而不知道编码方式?

65

在Python 2.x中,使用“类文件”对象:

sys.stdout.write(bytes_)
tempfile.TemporaryFile().write(bytes_)
open('filename', 'wb').write(bytes_)
StringIO().write(bytes_)

如何在 Python 3 中做相同的事情?

如何编写等效于 Python 2.x 代码的代码?

def write(file_, bytes_):
    file_.write(bytes_)

注意:sys.stdout并不总是语义上的文本流。有时将其视为字节流可能会更有利。例如,在远程机器上创建目录的加密归档

tar -c dir/ | gzip | gpg -c | ssh user@remote 'dd of=dir.tar.gz.gpg'

在这种情况下使用Unicode是没有意义的。

2个回答

74

关键是使用操作字节的API,而不是字符串。

sys.stdout.buffer.write(bytes_)

正如文档所解释的那样,您还可以使用detach方法来将流分离,使其默认为二进制格式。

这将访问底层字节缓冲区。

tempfile.TemporaryFile().write(bytes_)

这已经是一个字节API了。

open('filename', 'wb').write(bytes_)

正如'b'所代表的,这是一个字节级别的API。

from io import BytesIO
BytesIO().write(bytes_)

BytesIO 是字节级别等同于 StringIO

编辑:write 可以直接在任何二进制文件类对象上正常工作。因此,一般解决方案就是找到正确的API。


有没有一种方法可以编写通用函数而不需要使用类型检查,例如 isinstance(file_, io.TextIOWrapper) 等。 - jfs
@J.F.,Python 3专门设计用于正确处理文本与二进制之间的区分。如果不知道编码方式,就无法正确地在二进制和文本之间进行转换。因此,没有办法编写一个通用函数将字节写入文本流中。《Dive Into Python 3》有一篇很好的文章介绍了这个问题。 - Matthew Flaschen
这个问题特别涉及到字节。例如,os.write(sys.stdout.fileno(), bytes_) - jfs
所以答案是:传递一个对象,其“.write()”方法接受字节;没有捷径。 - jfs
@MatthewFlaschen: 当执行open('filename', 'wb').write(bytes_)时,出现错误NameError: name 'bytes_' is not defined - timekeeper
@AayushKumarSingha:bytes_ 是你的数据,例如 bytes_ = b'\x89PNG\r\n\x1a\n' - jfs

33

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接