2

私はASCIIでビットの範囲を含むテキストファイルを持っています:

cat myFile.txt
0101111011100011001...

これをバイナリモードで他のファイルに書き込んで、16進エディタで読み取れるようにします。どうすればそれに到達できますか?私はすでにそれを次のようなコードで変換しようとしました:

f2=open(fileOut, 'wb')
    with open(fileIn) as f:
      while True:
            c = f.read(1)
            byte = byte+str(c)
            if not c:
                print "End of file"
                break
            if count % 8 is 0:
                count = 0 
                print hex(int(byte,2))
                try:
                    f2.write('\\x'+hex(int(byte,2))[2:]).zfill(2)
                except:
                     pass
                byte = ''
            count += 1

しかし、それは私がやろうとしていたことを達成しませんでした。ヒントはありますか?

4

2 に答える 2

2
  • 一度に1バイトの読み取りと書き込みは非常に遅くなります。f.readおよびを呼び出すたびにファイルからより多くのデータを読み取るだけで、コードを約45倍高速化できますf.write

    |------------------+--------------------|
    | using_loop_20480 | 8.34 msec per loop | 
    | using_loop_8     | 354 msec per loop  |
    |------------------+--------------------|
    

    using_loopこの投稿の下部に表示されているコードです。using_loop_20480チャンクサイズ=1024*20のコードです。これは、一度に20480バイトがファイルから読み取られることを意味します。using_loop_1チャンクサイズ=1の同じコードです。

  • についてcount % 8 is 0is数値の比較には使用しないでください。== 代わりに使用してください。is間違った結果をもたらす可能性のあるいくつかの例を次に示します(投稿したコードにはないかもしれませんが、一般的に、isここでは適切ではありません)。

    In [5]: 1L is 1
    Out[5]: False
    
    In [6]: 1L == 1
    Out[6]: True
    
    In [7]: 0.0 is 0
    Out[7]: False
    
    In [8]: 0.0 == 0
    Out[8]: True
    
  • それ以外の

    struct.pack('{n}B'.format(n = len(bytes)), *bytes)
    

    あなたが使うことができます

    bytearray(bytes)
    

    タイピングが少ないだけでなく、少し速くなります。

    |------------------------------+--------------------|
    |             using_loop_20480 | 8.34 msec per loop |
    | using_loop_with_struct_20480 | 8.59 msec per loop |
    |------------------------------+--------------------|
    

    バイト配列は、データを文字列と数列と見なす間のギャップを埋めるため、このジョブに適しています。

    In [16]: bytearray([97,98,99])
    Out[16]: bytearray(b'abc')
    
    In [17]: print(bytearray([97,98,99]))
    abc
    

    上記のようにbytearray(bytes)、バイト配列に一連のint(in)を渡すことでバイト配列を定義でき range(256)、文字列であるかのように書き出すことができますg.write(bytearray(bytes))


def using_loop(output, chunksize):
    with open(filename, 'r') as f, open(output, 'wb') as g:
        while True:
            chunk = f.read(chunksize)
            if chunk == '':
                break
            bytes = [int(chunk[i:i+8], 2)
                     for i in range(0, len(chunk), 8)]
            g.write(bytearray(bytes))

チャンクサイズが8の倍数であることを確認してください。


これは、テーブルの作成に使用したコードです。prettytableもこれと同様のことを行うことに注意してください。私のハックではなく、それらのコードを使用することをお勧めします:table.py

これは、コードの時間を計るために使用したモジュールutils_timeit.pyです。(table.pyを使用します)。

そして、これが私が時間を計るために使用したコードusing_loop(および他のバリアント)です:timeit_bytearray_vs_struct.py

于 2012-12-18T18:41:30.087 に答える
1

使用struct

import struct
...
f2.write(struct.pack('b', int(byte,2))) # signed 8 bit int

また

f2.write(struct.pack('B', int(byte,2))) # unsigned 8 bit int
于 2012-12-18T12:38:27.080 に答える