带有ASCII文本标头的二进制输入,从stdin读取

布伦特·布拉德本

我想从标准输入中读取二进制PNM图像文件。该文件包含一个编码为ASCII文本的标头和一个二进制有效载荷。作为读取标题的简化示例,我创建了以下代码段:

#! /usr/bin/env python3
import sys
header = sys.stdin.readline()
print("header=["+header.strip()+"]")

我将其作为“ test.py”(从Bash shell)运行,在这种情况下,它可以正常工作:

$ printf "P5 1 1 255\n\x41" |./test.py 
header=[P5 1 1 255]

但是,二进制有效负载的微小变化就会破坏它:

$ printf "P5 1 1 255\n\x81" |./test.py 
Traceback (most recent call last):
  File "./test.py", line 3, in <module>
    header = sys.stdin.readline()
  File "/usr/lib/python3.4/codecs.py", line 313, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x81 in position 11: invalid start byte

有没有简单的方法可以在Python 3中实现此目的?

布伦特·布拉德本

文档中,可以bytes使用sys.stdin.buffer.read()以下命令从stdin读取二进制数据(作为type

要从标准流写入二进制数据或从标准流读取二进制数据,请使用基础二进制缓冲区对象。例如,要将字节写入stdout,请使用sys.stdout.buffer.write(b'abc')。

因此,这是您可以采取的一个方向-以二进制模式读取数据。readline()以及其他各种功能仍然有效。捕获ASCII字符串后,可以使用将该字符串转换为文本,以decode('ASCII')进行其他特定于文本的处理。

或者,您可以io.TextIOWrapper()用来指示latin-1输入流上字符集的使用这样,隐式解码操作本质上将是传递操作-因此数据将是类型str(表示文本),但是数据是从二进制文件以1到1映射表示的(尽管它可以每个输入字节使用一个以上的存储字节)。

这是在两种模式下均可使用的代码:

#! /usr/bin/python3

import sys, io

BINARY=True ## either way works

if BINARY: istream = sys.stdin.buffer
else:      istream = io.TextIOWrapper(sys.stdin.buffer,encoding='latin-1')

header = istream.readline()
if BINARY: header = header.decode('ASCII')
print("header=["+header.strip()+"]")

payload = istream.read()
print("len="+str(len(payload)))
for i in payload: print( i if BINARY else ord(i) )

使用以下Bash命令测试每个可能的1像素有效负载:

for i in $(seq 0 255) ; do printf "P5 1 1 255\n\x$(printf %02x $i)" |./test.py ; done

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章