用Python写一个二进制整数或字符串到一个文件中

12 人关注

我在Python中有一个字符串(也可以是一个整数),我想把它写到一个文件中。它只包含1和0,我想把这个1和0的模式写到文件中。我想直接写入二进制,因为我需要存储大量的数据,但只有某些值。我认为没有必要占用每个值8位的空间,而我只需要3位。

举例来说。假设我将二进制字符串 "01100010" 写到一个文件中。如果我在文本编辑器中打开它,它将显示 b (01100010是b的ascii代码)。不过,不要感到困惑。我不想写ascii代码,这个例子只是想说明我想直接向文件写入字节。

澄清一下。

My string looks something like this:

binary_string = "001011010110000010010"

它不是由数字或字符的二进制代码组成的。它包含只与我的程序有关的数据。

python
file
file-io
binary
KFox
KFox
发布于 2013-06-03
5 个回答
Ryan Haining
Ryan Haining
发布于 2016-03-31
已采纳
0 人赞同

要写出一个字符串,你可以使用文件的 .write 方法。 要写出一个整数,你将需要使用 struct 模块

import struct
with open('file.dat', 'wb') as f:
    if isinstance(value, int):
        f.write(struct.pack('i', value)) # write an int
    elif isinstance(value, str):
        f.write(value) # write a string
    else:
        raise TypeError('Can only write str or int')

然而,int和字符串的表示方法不同,你可能需要使用bin函数来将其变成一个0和1的字符串。

>>> bin(7)
'0b111'
>>> bin(7)[2:] #cut off the 0b
'111'

但也许处理所有这些int的最好方法是为文件中的二进制字符串决定一个固定的宽度,并像这样转换它们。

>>> x = 7
>>> '{0:032b}'.format(x) #32 character wide binary number with '0' as filler
'00000000000000000000000000000111'
    
KFox
这不是我想要的。我编辑了这个问题,以更具体地显示我需要做什么。
@KFox 你是说你想要一个函数:给定一个由0和1组成的 int str ,你想把它作为一个int的二进制表示写入文件,而不是一个0/1字符的字符串。 我不确定你说的 "当我只需要3 "是什么意思,你的意思是你只在最大的值中使用24位吗?
KFox
Sorry, it 比较不清楚。反正我现在已经找到了答案。不过还是要感谢你的回答。
KFox
KFox
发布于 2016-03-31
0 人赞同

好吧,经过相当多的搜索,我找到了一个答案。我相信你们其他人根本没有理解(这可能是我的错,因为我不得不编辑两次以使其清晰)。我发现 here .

答案是把每一个数据分割开来,转换成二进制的整数,然后把它们放在一个二进制数组中。之后,你可以使用数组的 tofile() 方法来写入文件。

from array import *
bin_array = array('B')
bin_array.append(int('011',2))
bin_array.append(int('010',2))
bin_array.append(int('110',2))
with file('binary.mydata', 'wb') as f:
    bin_array.tofile(f)
    
Aya
Aya
发布于 2016-03-31
0 人赞同

我想把这个1和0的模式写到一个文件里。

如果你的意思是你想从一个字符串写一个比特流到一个文件,你需要这样的东西...

from cStringIO import StringIO
s = "001011010110000010010"
sio = StringIO(s)
f = open('outfile', 'wb')
while 1:
    # Grab the next 8 bits
    b = sio.read(8)
    # Bail if we hit EOF
    if not b:
        break
    # If we got fewer than 8 bits, pad with zeroes on the right
    if len(b) < 8:
        b = b + '0' * (8 - len(b))
    # Convert to int
    i = int(b, 2)
    # Convert to char
    c = chr(i)
    # Write
    f.write(c)
f.close()

...for which xxd -b outfile shows...

0000000: 00101101 01100000 10010000                             -`.
    
当8位块以 "1 "开始时,这就会被打破,因为此时utf-8编码是 longer .这在Python 3中是可以避免的。 using to_bytes .
ThorSummoner
ThorSummoner
发布于 2016-03-31
0 人赞同

简要的例子。

my_number = 1234
with open('myfile', 'wb') as file_handle:
    file_handle.write(struct.pack('i', my_number))
with open('myfile', 'rb') as file_handle:
    my_number_back = struct.unpack('i', file_handle.read())[0]
    
SO_fix_the_vote_sorting_bug
SO_fix_the_vote_sorting_bug
发布于 2016-03-31
0 人赞同

附加到一个 array.array 上每次3位,仍然会产生8位的每个值。 将 011 010 110 追加到一个数组并写入磁盘将产生以下输出。 00000011 00000010 00000110 。 注意里面所有的零都是填充过的。

看起来,你是想把二进制三字节 "压缩 "成字节,以节省空间。 鉴于你问题中的例子字符串,你可以把它转换成一个整数列表(每次8位),然后直接把它写入文件。 这将把所有的比特打包,每个值只用3比特而不是8比特。

Python 3.4 example

original_string = '001011010110000010010'
# first split into 8-bit chunks
bit_strings = [original_string[i:i + 8] for i in range(0, len(original_string), 8)]
# then convert to integers
byte_list = [int(b, 2) for b in bit_strings]
with open('byte.dat', 'wb') as f:
    f.write(bytearray(byte_list))  # convert to bytearray before writing

byte.dat的内容。

  • hex: 2D 60 12
  • binary (by 8 bits): 00101101 01100000 00010010
  • 二进制(由3位)。【替换代码8

  •