1

ハフマン エンコーディング文字列をバイナリ python に変換する方法に問題があります。

この質問には、ハフマン アルゴリズムは関係ありません。

次のようになります。

エンコードされたハフマン文字列を取得できます01010101010、これは文字列です。

しかし今、文字列表現を実際のバイナリに保存したいと考えています。

ハフマンでエンコードされた文字列では、すべての 0 と 1 がbyteです。

私が欲しいのは、すべての 0 と 1 が少しです。

どうすればPythonでそれを行うことができますか?

編集1:

私の問題を十分に明確に説明していないことを許してください。

0 と 1 を 2 進数に書き込む現在のアプローチについて説明します。

たとえば、文字列 s='010101010' をコード化できます。

  1. 私はintそれを整数に変換するために使用します
  2. 次にunichr、それを文字列に変換して、ファイルに書き込むことができるようにします
  3. 文字列をバイナリモードでファイルに書き込みます

また、ハフマン コードをデコードするには、ファイルを読み取る必要があります。

だから私のアプローチは、

  1. ファイルからバイトを読み取る
  2. それらをintに戻します
  3. int をバイナリ表現文字列に変換します。
  4. 文字列をデコードする

そして、ステップ 2で問題が発生し、私は無知になりました。

一部のハフマン文字列は短く ( のように10)、一部は長く ( 010101010101001) になる可能性があります。これにより、int値のバイト長が異なります(短い文字列には1バイトしかかからないものもあれば、長い文字列には2バイト以上かかるものもあります)

次のコードは、私の問題を示しています。

ss=['010101','10010101010'] 
# first one is short and takes only one byte in its int value
# second one is long and takes two bytes   

print 'write it to file'
with open('binary.bin','wb') as f:
    for s in ss:
        n=int(s,2)
        print n
        s=unichr(n)
        f.write(s)

print 'read it to file'
with open('binary.bin','rb') as f:
    for s in f.read(): 
        print ord(s)

一部で秒単位で1 バイトずつ読み込んでいますが、これは実際には正しくありません。文字列10010101010は 2 バイトを占めるためです。

ファイルからそれらのバイトを読み取るとき、一度に何バイトを読み取る必要がありますか?

4

3 に答える 3

2

ある程度は理にかなっているが、それでも不正確さが含まれている1つの可能なアプローチ(ビット文字列ライブラリを使用):

ビット文字列ライブラリを使用する( MechanicalsnailMarcBのおかげで)

ファイルへの書き込み用。

手順:

  1. プレーンテキストをバイナリ表現文字列にエンコードする
  2. これらすべての文字列を連結して、1つの長い文字列を形成します
  3. bitstring.BitArrayを使用して16進形式に変換します
  4. 16進文字列をファイルに書き込む

読むために:

  1. ファイルから16進文字列を読み取ります
  2. BitArrayを使用してビット文字列に変換し直します
  3. デコードを開始します

コード:

ss=['01010100','10010101010','010101110101010101'] #encoded message


from bitstring import BitArray,BitStream
print 'write it to file'
with open('binary.bin','wb') as f:
    s=''.join(ss);
    b=BitArray(bin=s)                 
    f.write(b.tobytes())# thanks to Scott, tobytes() method is very useful

print 'read it to file'
b=BitArray(filename='binary.bin')
print b.bin
于 2011-08-29T12:31:16.223 に答える
2

Python には、使用できる 2 つの異なる「バイナリ」表現があります。

ビッグナム

1 つは「bignum」または任意精度の整数です。この型はlongPython 2.x とintPython 3.x で呼び出されます。名前が示すように、この表現は意味的には任意の長さの整数であるため、結果の数値に対して算術演算を行う場合に便利です。2 進数の文字列を解析するには、次を使用します。

# Python 2
long(digit_str, 2)

また

# Python 3
int(digit_str, 2)

bitstring library

Alternatively, as Marc B suggested in the comments, use the bitstring library. Specifically, for conversion, use the bitstring.pack function.

For Huffman coding, using bitstring is probably preferable to storing data in a byte-string, since Huffman codes are generally not multiples of 8 bits; bitstring lets you manipulate bit-strings of arbitrary lengths. Disadvantage: bitstring is not part of the standard library.

于 2011-08-29T03:47:52.843 に答える
1

数値に変換する必要がある文字列があります。intオプションの「ベース」を引数として取ります。したがって、例の文字列については、

>>> int('01010101010', 2)
682

数値 (文字列ではない) を取得したら、「実際の」2 進数を求めても意味がありません。数値は同じであるため、任意の基数で表示できます。つまり、バイナリ100は decimal と同じ数値4であり、プログラム内では異なる数値ではありません。したがって、文字列を数値に変換すると、その中のビットをいじることができます。

于 2011-08-29T03:02:41.383 に答える