Effektivste Art für Dateien r/w

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
may24x
User
Beiträge: 48
Registriert: Montag 2. September 2013, 06:44

Hallo zusammen,
ich baue gerade ein Script was die Header Informationen gewisser Dateien ändert.
D.h. ich lese erst mal binär 32 Bytes, analysiere bzw. verbiege sie und schreibe sie in ein neues File.

Nur jetzt müssen nur noch die restlichen 500MB (unverändert) hinterher ...
Und hier die Frage, wie mache ich das am effektivsten ... ohne mir die 500MB komplett in den Speicher zu knallen ...
BlackJack

@may24x: Schau Dir mal das `shutil`-Modul aus der Standardbibliothek an.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1258
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Code: Alles auswählen

In [1]: import shutil

In [2]: fd_writer = open('test.bin', 'wb')

In [3]: fd_reader = open('./Downloads/virtio-win-drivers-20120712-1.iso', 'rb')

In [4]: fd_writer.write(b'FOO_TEST')
Out[4]: 8

In [5]: shutil.copyfileobj(fd_reader, fd_writer)

In [6]: fd_writer.close(), fd_reader.close()
Out[6]: (None, None)

In [7]: fd = open('test.bin', 'rb')

In [8]: fd.read(10)
Out[8]: b'FOO_TEST\x00\x00'
Ich denke mal, dass copyfileobj sehr effektiv ist. Erst schreibst du den Header in die Datei und danach macht copyfileobj den Rest. Wenn du den Header von der ersten Datei entfernen willst/musst, kannst du das mit fd_in.seek(headersize) machen. Die Kopieroperation müsste dann bei den beiden Objekten an der Stelle wo der gerade ist, einfach weiter machen.
Zuletzt geändert von Anonymous am Donnerstag 1. Juni 2017, 14:32, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Sirius3
User
Beiträge: 18299
Registriert: Sonntag 21. Oktober 2012, 17:20

@DeaD_EyE: was ist der Sinn, ein Tuple aus zwei None-Werten zu bilden, das man dann nicht benutzt?
may24x
User
Beiträge: 48
Registriert: Montag 2. September 2013, 06:44

Hm scheint als würde der "seek" nicht funktionieren ...

Code: Alles auswählen

### build new file
in_file = open(inputfile, 'br')
out_file = open(outputfile, 'bw')

### part 1
data = in_file.read(66)
out_file.write(data)

### part 2
out_file.write(mod_data)

### part 3
shutil.copyfileobj(in_file.seek(72), out_file)
in_file.close()
out_file.close()
Traceback (most recent call last):
File "Q:\Lego Star wars\test\hevc_FPS-changer.py", line 8
shutil.copyfileobj((in_file.seek(72)), out_file)
File "C:\Users\vm\AppData\Local\Programs\Python\Python36-
ne 79, in copyfileobj
buf = fsrc.read(length)
AttributeError: 'int' object has no attribute 'read'
Zuletzt geändert von Anonymous am Donnerstag 1. Juni 2017, 15:35, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 18299
Registriert: Sonntag 21. Oktober 2012, 17:20

@may24x: seek liefert kein Dateiobjekt zurück, sondern den vorherige Wert des Dateipositionszeigers.
may24x
User
Beiträge: 48
Registriert: Montag 2. September 2013, 06:44

exakt ... aber wie kann ich das Datenmodell um besagte 72 bytes "kürzen" ?
Denn sonst hab ich die Daten ja doppelt drinne stehen ... ?

oder langt etwa ein:

Code: Alles auswählen

in_file.seek(72)
shutil.copyfileobj(in_file, out_file)
Zuletzt geändert von Anonymous am Donnerstag 1. Juni 2017, 15:36, insgesamt 1-mal geändert.
Grund: Quelltext in Codebox-Tags gesetzt.
may24x
User
Beiträge: 48
Registriert: Montag 2. September 2013, 06:44

Ah, hat sich erledigt :)
Ja, es geht tatsächlich so: Erst den Pointer mit dem "seek" setzen und dann einfach kopieren ...

Code: Alles auswählen

### part 3
in_file.seek(72)
shutil.copyfileobj(in_file, out_file)
Vielen Dank für eure Hilfe
BlackJack

@may24x: Ich persönlich hätte das `seek()` durch ein ``read(6)`` ausgedrückt, dann muss die Datei nicht „seekable“ sein.

Ein bisschen verwirrend finde ich die Namensgebung bei `in_file` und `inputfile` und `out_file` und `outputfile`, weil ja nur zwei davon wirklich Datei-Objekte sind und die anderen beiden Datei*namen*.
Antworten