2016-04-16 15 views
1

Ich experimentiere gerade damit, wie Python 3 beim Lesen und Schreiben von Daten Bytes handhabt, und ich bin auf ein besonders beunruhigendes Problem gestoßen, das ich anscheinend nicht finden kann. Ich lese baßweise Bytes aus einer JPEG-Datei, wandle sie unter Verwendung von ord() in eine ganze Zahl um, gebe dann die Bytes mit der Zeile chr(character).encode('utf-8') an ihr ursprüngliches Zeichen zurück und schreibe sie in eine JPEG-Datei zurück. Kein Problem, oder? Nun, wenn ich versuche, die JPEG-Datei zu öffnen, erhalte ich eine Windows 8.1-Benachrichtigung, dass das Foto nicht geöffnet werden kann. Wenn ich die beiden Dateien gegeneinander überprüfe, ist einer 5.04MB und der andere 7.63MB, was mich sehr verwirrt hat.Mehr Daten in Datei schreiben als lesen?

def __main__(): 
    operating_file = open('photo.jpg', 'rb') 

    while True: 
     data_chunk = operating_file.read(64*1024) 
     if len(data_chunk) == 0: 
      print('COMPLETE') 
      break 
     else: 
      new_operation = open('newFile.txt', 'ab') 
      for character in list(data_chunk): 
       new_operation.write(chr(character).encode('utf-8')) 


if __name__ == '__main__': 
    __main__() 

Dies ist der genaue Code, den ich verwende, irgendwelche Ideen, was passiert und wie ich es beheben kann?

HINWEIS: Ich gehe davon aus, dass die Liste der Zahlen, die list(data_chunk) bietet, entspricht ord().

+1

Warum verwenden Sie 'liste'? Soweit ich sehen kann, wird 'data_chunk' ein Byte-Objekt sein, das auf Byte zu einem Zeitpunkt iteriert werden kann. Ich bin auch Rätsel, warum Sie uff-8 angeben. Wenn Sie Bytes lesen, möchten Sie nicht, dass sie in Zeichen konvertiert werden. – cdarke

+0

Versuchen Sie Ihren Code auf einer viel kleineren Testdatei - es muss kein echtes JPEG sein - mit einer kleineren "Chunk-Größe", und vergleichen Sie dann die Größe und den Inhalt der beiden Dateien. Sie können auch leicht testen, ob Ihre Annahme richtig ist. Übrigens, die richtige Methode zum Öffnen einer Datei zum Lesen im Binärmodus in Python 3 ist 'open (Dateiname, 'r', newline = '')'. Es ist etwas Ähnliches zum Schreiben. – martineau

+2

Codierung von Bytes als UTF-8 zum Schreiben einer JPEG-Datei ist falsch. Es wird jedes Byte mit einem Wert über 0x7F aufnehmen und es als mehrere Bytes codieren, wodurch die Daten beschädigt werden. –

Antwort

2

Hier ist ein einfaches Beispiel, das Sie sich wünschen kann, mit spielen:

import sys 

f = open('gash.txt', 'rb') 
stuff=f.read() # stuff refers to a bytes object 
f.close() 

print(stuff) 

f2 = open('gash2.txt', 'wb') 

for i in stuff: 
    f2.write(i.to_bytes(1, sys.byteorder)) 

f2.close() 

Wie Sie sehen können, die Bytes Objekt ist iterable, aber in der for Schleife erhalten wir eine int in i zurück. Um das zu einem Byte zu konvertieren, verwende ich int.to_bytes() Methode.

+0

Das OP verwendet Python 3, daher ist die Art, wie Sie Dateien für den Binärmodus öffnen, falsch (auch wenn es auf einigen Betriebssystemen funktioniert). – martineau

+0

@martineau: Dieser Code funktioniert gut auf Python 3.5. Was ist daran falsch? – cdarke

+1

Danke, ich konnte damit mein Problem lösen. – TheMountainFurnaceGabriel

0

Wenn Sie einen Codepunkt haben und ihn in UTF-8 codieren, ist es möglich, dass das Ergebnis mehr Bytes als das Original enthält.

Ein spezifisches Beispiel finden Sie unter WikiPedia page und berücksichtigen Sie den hexadezimalen Wert 0xA2.

Dies ist ein einzelner Binärwert, weniger als 255, aber wenn er nach UTF8 codiert wird, wird er 0xC2, 0xA2.

Vorausgesetzt, dass Sie Bytes aus Ihrer Quelldatei ziehen, meine erste Empfehlung wäre, einfach die Bytes direkt an den Schreiber Ihrer Zieldatei übergeben.

Wenn Sie versuchen zu verstehen, wie Datei-I/O funktioniert, achten Sie auf encode(), wenn Sie einen binären Dateimodus verwenden. Binärdateien müssen nicht codiert und nicht dekodiert werden - sie sind Rohdaten.