Zpracování binárního souboru

Dotaz z koference:

Ahoj, potreboval by jsem nacist binarni soubor, zmenit par bitu a potom ho zase ulozit. Da se v Pythonu pracovat primo s binarnimy daty?

Odpověď:

První problém spočívá v tom, že soubory musíme otevřít v binárním režimu. To znamená, že konstruktoru file() nebo funkci open() musíme v druhém parametru zadat rb (pro binární čtení) nebo wb (pro binární zápis).

Druhá část problému je daná tím, že string (pokud není unicodový) je interpretován jako posloupnost bajtů. Souborové metody read() a write() pracují s řetězci. Pokud je soubor otevřen binárně, interpretují je jako posloupnosti bajtů.

Komplikace "bajt/znak řetězce" spočívá v tom, že si číselnou podobu bajtu musíme sami konvertovat na znak a zpět.

Poslední část problému spočívá v tom, že string se nedá modifikovat na místě (při modifikaci se vytváří modifikovaná kopie). Proto může být NĚKDY výhodnější převést si to na seznam (nebo použít modul array, pokud by seznam nestačil vzhledem k efektivnosti). Prvky seznamu můžeme měnit a výsledný seznam můžeme spojit do řetězce, který zapíšeme binárně do výstupního souboru. Příklad:

 import sys

 def zpracujSoubor(fnameIn, fnameOut):
     fin = file(fnameIn, 'rb')
     lst = list(fin.read())
     fin.close()

     # Cvicne zmenime prvni dva bajty.
     lst[0] = chr(13)
     lst[1] = chr(10)

     fout = file(fnameOut, 'wb')
     fout.write(''.join(lst))
     fout.close()

 def main():

     # Pripravime si testovaci binarni soubor.
     fout = file('input.bin', 'wb')
     for n in xrange(256):
         fout.write(chr(n))
     fout.close()

     # Zpracujeme binarni soubor.
     zpracujSoubor('input.bin', 'output.bin')

 if __name__ == '__main__':
     main()

Poslední dva řádky spustí funci main(). Ve funkci main() se vygeneruje testovací binární soubor input.bin (256 bajtů s kódy 0 až 255) a zavolá se funkce pro modifikaci tohoto souboru zpracujSoubor(). Ta binárně načte celý obsah vstupního souboru (řetězec) a převede jej na seznam. Modifikovaný seznam se spojí do řetězce a zapíše do výstupního binárního souboru.