Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 带ASCII文本标题的二进制输入,从标准输入法读取_Python 3.x_Unicode_Binary_Ascii - Fatal编程技术网

Python 3.x 带ASCII文本标题的二进制输入,从标准输入法读取

Python 3.x 带ASCII文本标题的二进制输入,从标准输入法读取,python-3.x,unicode,binary,ascii,Python 3.x,Unicode,Binary,Ascii,我想从stdin读取一个二进制图像文件。该文件包含一个编码为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" |.

我想从stdin读取一个二进制图像文件。该文件包含一个编码为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
$printf“P5 1 1 255\n\x81”|/test.py
回溯(最近一次呼叫最后一次):
文件“/test.py”,第3行,在
header=sys.stdin.readline()
文件“/usr/lib/python3.4/codecs.py”,第313行,解码中
(结果,消耗)=自身缓冲区解码(数据,自身错误,最终)
UnicodeDecodeError:“utf-8”编解码器无法解码位置11中的字节0x81:无效的开始字节
有没有一种简单的方法可以在Python 3中实现这一点?

从中,可以使用sys.stdin.buffer.read()从stdin读取二进制数据(类型为
字节
):

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

这是一个你可以选择的方向——以二进制模式读取数据
readline()
和其他各种功能仍在工作。捕获ASCII字符串后,可以使用
解码('ASCII')
将其转换为文本,以进行其他特定于文本的处理

或者,您可以使用
io.TextIOWrapper()
来指示在输入流上使用
拉丁-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

要读取二进制数据,应使用二进制流,例如,使用:


您是否尝试更改输入编码@男主角:谢谢你的提示。该方法指出了一个可能的解决方案——尽管对任意二进制数据应用Unicode解码有点困难。使用
latin-1
作为二进制数据的管道的困难是因为它是,而不是。
#!/usr/bin/env python3
import sys

sys.stdin = sys.stdin.detach() # convert to binary stream
header = sys.stdin.readline().decode('ascii') # b'\n'-terminated
print(header, end='')
print(repr(sys.stdin.read()))