Pythonに文字列(整数の場合もあります)があり、ファイルに書き込みたいです。1と0のみが含まれています。1と0のパターンを書き込みたいです。大量のデータを格納する必要があるため、バイナリを直接書き込みたいのですが、特定の値のみです。3つしか必要ない場合は、値ごとに8ビットを使用するスペースをとる必要はありません。
例えば。バイナリ文字列を書くとしましょう"01100010"
ファイルに。テキストエディタで開くと、b
と表示されます(01100010はbのASCIIコードです)。ただし、混同しないでください。私はASCIIコードを書きたくありません。例は、ファイルに直接バイトを書きたいことを示すためだけのものでした。
明確化:
私の文字列は次のようになります。
binary_string = "001011010110000010010"
数字や文字のバイナリコードで構成されていません。私のプログラムにのみ関連するデータが含まれています。
さて、もう少し検索した後、私は答えを見つけました。残りの皆さんは単に理解していなかったと思います(明確にするために2回編集しなければならなかったので、おそらく私のせいでした)。私はそれを見つけました ここ 。
答えは、各データを分割し、それらを2進整数に変換してから、2進配列に入れることでした。その後、配列の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))
f = file('binary.mydata','wb')
bin_array.tofile(f)
f.close()
文字列を書き出すには、ファイルの.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とstringの表現は異なります。代わりに、bin
関数を使用して、0と1の文字列に変換することができます。
>>> bin(7)
'0b111'
>>> bin(7)[2:] #cut off the 0b
'111'
しかし、これらすべてのint
sを処理する最良の方法は、ファイル内のバイナリ文字列の固定幅を決定し、次のように変換することです。
>>> x = 7
>>> '{0:032b}'.format(x) #32 character wide binary number with '0' as filler
'00000000000000000000000000000111'
その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()
...そのためにxxd -b outfile
ショー...
0000000: 00101101 01100000 10010000 -`.
簡単な例:
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]
一度に3ビットをarray.array
に追加すると、すべての値に対して8ビットが生成されます。 011
、010
、および110
を配列に追加してディスクに書き込むと、次の出力が生成されます:00000011 00000010 00000110
。そこにあるすべての埋め込みゼロに注意してください。
代わりに、スペースを節約するために、バイナリトリプレットをバイトに「圧縮」したいようです。質問の文字列の例を考えると、それを整数のリスト(一度に8ビット)に変換してから、ファイルに直接書き込むことができます。これにより、値ごとに8ビットではなく3ビットのみを使用して、すべてのビットが一緒にパックされます。
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の内容:
2D 60 12
00101101 01100000 00010010
バイナリ(3ビット):001 011 010 110 000 000 010 010
^^ ^ (Note extra bits)
このメソッドは、最後の値を8ビット境界に揃えるようにパディングし、パディングは最上位ビット(上記の出力の最後のバイトの左側)に行くことに注意してください。したがって、注意が必要です。文字列の長さを8の倍数にするために、元の文字列の末尾にゼロを追加する必要があります。