问题 Python - 将文件内容转换为二进制数组


文件内容:

40 13 123
89 123 2223
4  12  0

我需要存储整个 .txt 将文件作为二进制数组存储,以便稍后将其发送到需要二进制输入的服务器端。


我看过Python的 字节组 文档。  我引用:

返回一个新的字节数组。 bytearray类型是0 <= x <256范围内的可变整数序列。它具有可变序列的大多数常用方法,在可变序列类型中描述,以及字节类型具有的大多数方法,请参阅字节和字节数组方法。


我的数字大于256,我需要一个 字节组 数字大于256的数据结构。


8573
2018-03-10 09:05


起源

你的意思是你想将文本表示存储为int32数组吗? - xtofl
@xtofl是的。但我的问题是,在我对每个数字执行此操作后,我希望将它放在二进制对象中?如果我访问第一行,我得到二进制表示中的第一个数字。 - Tony Tannous
你有一个你想要的例子吗? "101010" 不是二进制对象,它是一个二进制表示42的字符串。 42,作为整数,已经存储为Python的二进制文件。 - Eric Duminil
@EricDuminil是先生,对不起我的错误表达。一个字节是8位,可以发送为 binary 数据。我需要有一个二进制数的序列,以便我知道何时停止阅读以了解我的第一个数字,第二个数字等等。一种方法是xtofl表示以32位表示。但我无法使bytearray存储超过8位,因为任何大于256的数据都无法存储。 - Tony Tannous
所以只需使用一个int数组就可以了。服务器不能准确指定它所期望的格式吗? - Eric Duminil


答案:


你可能会用 array/memoryview 途径

import array
a = array.array('h', [10, 20, 300]) #assume that the input are short signed integers
memv = memoryview(a)
m = memv.cast('b') #cast to bytes
m.tolist()

然后给出 [10, 0, 20, 0, 44, 1]

根据用途,人们也可以这样做:

L = array.array('h', [10, 20, 300]).tostring()
list(map(ord, list(L)))

这也给了 [10, 0, 20, 0, 44, 1]


7
2018-03-10 09:23



太好了!我也看到了 array.from_list(...)。 - xtofl
TypeError: cannot make memory view because object does not have the buffer interface 我读到array.array对象只在python 3上支持吗? stackoverflow.com/questions/4877866/... - Tony Tannous
@xtofl它在Python 3上工作正常,但不幸的是,Python 2.7不支持在数组上应用memoryview - bugs.python.org/issue17145 - ewcz
@TonyTannous然后我会改变 'h' 至 'd',即用整数替换短整数... - ewcz
我删除了评论。它现在有效。请给我几分钟。完善! - Tony Tannous


您可以读入文本文件并将每个'word'转换为int:

with open(the_file, 'r') as f:
    lines = f.read_lines()
    numbers = [int(w) for line in lines for w in line.split()]

然后你必须打包 numbers 用二进制数组 struct

binary_representation = struct.pack("{}i".format(len(numbers)), *numbers)

如果您想要写入这些数据 以二进制格式,你必须在打开目标文件时指定:

with open(target_file, 'wb') as f:
   f.write(binary_representation)

3
2018-03-10 09:27



我同意这种双列表理解语法更具可读性,但不幸的是,它不起作用。此外,如果你迭代一个字符串,你会得到字符,而不是单词。 - Eric Duminil
猛击。这是相反的方式。谢谢 - xtofl


不是bytearray

来自 bytearray 文件,它只是0 <= x <256范围内的整数序列。

例如,您可以像这样初始化它:

bytearray([40,13,123,89,123,4,12,0])
# bytearray(b'(\r{Y{\x04\x0c\x00')

由于整数已经以二进制形式存储,因此您无需转换任何内容。

你现在的问题变成了:你想做什么 2223 ?

>>> bytearray([2223])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: byte must be in range(0, 256)

uint32或int32数组?

要读取一个文件,您可以使用:

import re
with open('test.txt') as f:
    numbers = [int(w) for line in f for w in re.split(' +', line)]
    print numbers
    #[40, 13, 123, 89, 123, 2223, 4, 12, 0]

一旦有了整数列表,就可以选择相应的低级别 Numpy数据结构,可能 uint32 要么 int32


2
2018-03-10 09:19





我需要这个  服务器 - 客户端模块,其功能之一需要一个 binary 输入。可以找到不同的节俭类型 这里

客户

myList = [5, 999, 430, 0]
binL = array.array('l', myList).tostring()
# call function with binL as parameter

服务器 我重建了这个清单

k = list(array.array('l', binL))
print(k)
[5, 999, 430, 0]

1
2017-08-01 07:43





尝试这个:

input.txt中:

40 13 123
89 123 2223
4  12  0

用于解析输入到输出的代码:

with open('input.txt', 'r') as _in:
    nums = map(bin, map(int, _in.read().split())) # read in the whole file, split it into a list of strings, then convert to integer, the convert to binary string

with open('output.txt', 'w') as out:
          out.writelines(map(lambda b: b + '\n', map(lambda n: n.replace('0b', ''), nums))) # remove the `0b` head from the binstrings, then append `\n` to every string in the list, then write to file

output.txt的:

101000
1101
1111011
1011001
1111011
100010101111
100
1100
0

希望能帮助到你。


0
2018-03-10 09:17



谢谢,但我不想把它作为二进制文件写入新文件,我需要将它保存在二进制对象中。像bytearray一样。但我感谢你的努力。谢谢。 - Tony Tannous
@TonyTannous:然后你的问题没有意义,看起来你不知道你想要发送什么。 - Eric Duminil
@EricDuminil他知道,但没有适当的条款。 - xtofl
@TonyTannous然后只使用一个列表 int秒。稍后您可以将其转换为您想要的任何内容:D - Szabolcs