2016-08-09 51 views
1

Ich versuche, eine von einem Messgerät erstellte Datei zu öffnen, finde die Metadaten entsprechenden Bytes und schreibe dann alles andere in eine neue Binärdatei. (Der Metadatenteil ist nicht das Problem: Ich kenne die Header und kann sie leicht finden. Machen wir uns keine Sorgen.)Kopieren von einer Binärdatei mit Python fügt neue Bytes (?)

Das Problem ist: wenn ich die Datei öffne und die Bytes in eine neue Datei schreibe, neue Bytes hinzugefügt, was die relevanten Daten durcheinander bringt. Genauer gesagt, jedes Mal, wenn in der ursprünglichen Datei ein 0A-Byte vorhanden ist, hat die neue Datei ein 0D-Byte davor. Ich habe ein paar Iterationen durchgeführt, um den Code zu trimmen, um das Problem zu finden. Hier ist die neueste und einfachste Version, auf drei verschiedene Arten, die alle das gleiche Ergebnis produzieren:

import os 
import mmap 

file_name = raw_input('Name of the file to be edited: ') 
f = open(file_name, 'rb') 

#1st try: using mmap, to make the metadata sarch easier 
s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 
full_data = s.read(len(s)) 
with open(os.path.join('.', 'edited', ('[mmap data]' + file_name + '.bin')), 'a') as data_mmap: 
    data_mmap.write(full_data) 

#2nd try: using bytes, in case mmap was giving me trouble 

f_byte = bytes(f.read()) 
with open(os.path.join('.', 'edited', ('[bytes data]' + file_name + '.bin')), 'a') as data_bytes: 
    data_bytes.write(f_byte) 

s.close() 
f.close() 

#3rd try: using os.read/write(file) instead of file.read() and file.write(). 
from os.path import getsize 

o = os.open(file_name,os.O_BINARY) #only available on Windows 
f_os = bytes(os.read(o,getsize(file_name))) 
with open(os.path.join('.', 'edited', ('[os data]' + file_name + '.bin')), 'a') as data_os: 
    os.write(data_os.fileno(),f_os) 

os.close(o) 

Die resultierenden Dateien alle identisch sind (im Vergleich zu HxD). Und sie sind fast identisch mit der ursprünglichen Datei, außer für die einzelnen neuen Bytes. Zum Beispiel liest die ursprüngliche Datei ab Offset 0120: A0 0A 00 00 während die neue Datei liest: A0 0D 0A 00 ... und dann ist alles bis zum nächsten Vorkommen von 0A in der ursprünglichen Datei identisch, wo wieder ein 0D Byte erscheint.

Da der Code wirklich einfach ist, nehme ich an, der Fehler kommt von der Lesefunktion (oder vielleicht von einem unvermeidlichen inhärenten Verhalten des Betriebssystems ... Ich benutze Python 2.7 auf Windows, BTW.) Ich vermutete auch das Datenformat zuerst, aber es scheint mir, es sollte irrelevant sein. Ich kopiere einfach alles, unabhängig vom Wert.

Ich fand keine Dokumentation, die helfen könnte, also ... weiß jemand, was das verursacht?

Edit: das gleiche Skript funktioniert übrigens gut auf Linux. Es war also kein großes Problem, aber sehr nervig.

+2

Sie öffnen die Quelldatei im Binärmodus, aber die Zieldatei im Textmodus. Öffnen Sie beide Dateien im Binärmodus, und Python wird nicht an Ihren Newline-Markierungen basteln. –

Antwort

4

Willkommen in der Welt der Endmarker! Wenn eine Datei im Textmodus unter Windows geöffnet ist, wird jedes rohe \n (hex 0x0a) als \r\n (hex 0x0d 0x0a) geschrieben.

Glücklicherweise ist es einfach zu beheben: einfach die Datei in Binär-Modus öffnen (beachten Sie die b):

with open(..., 'ab') as data_...: 

und die unerwünschte \r nicht mehr stören :-)

+0

Verdammt. Ich wusste, dass es etwas Einfaches sein musste, ich wusste nicht, dass es so einfach wäre! Danke! – bernatel