Es wurde vor kurzem gefragt how to do a file slurp in python und die akzeptierte Antwort vorgeschlagen etwas wie:Python Datei Slurp w/Endian-Umwandlung
with open('x.txt') as x: f = x.read()
Wie würde ich mich darüber, die Datei in und wandelt die Endian-Darstellung des lesen tun Daten?
Zum Beispiel habe ich eine 1-GB-Binärdatei, die nur eine Reihe von einzelnen Präzision Floats als Big Endian gepackt ist und ich möchte es in Little Endian konvertieren und dump in ein numpy Array. Unten ist die Funktion, die ich geschrieben habe, um dies zu erreichen, und ein echter Code, der sie aufruft. Ich benutze struct.unpack
die Endian-Konvertierung und versuchte, alles zu beschleunigen, indem Sie mmap
verwenden.
Meine Frage ist dann, verwende ich den slurp korrekt mit mmap
und struct.unpack
? Gibt es einen saubereren, schnelleren Weg, dies zu tun? Gerade jetzt, was ich habe funktioniert, aber ich würde wirklich gerne lernen, wie man das besser macht.
Vielen Dank im Voraus!
#!/usr/bin/python
from struct import unpack
import mmap
import numpy as np
def mmapChannel(arrayName, fileName, channelNo, line_count, sample_count):
"""
We need to read in the asf internal file and convert it into a numpy array.
It is stored as a single row, and is binary. Thenumber of lines (rows), samples (columns),
and channels all come from the .meta text file
Also, internal format files are packed big endian, but most systems use little endian, so we need
to make that conversion as well.
Memory mapping seemed to improve the ingestion speed a bit
"""
# memory-map the file, size 0 means whole file
# length = line_count * sample_count * arrayName.itemsize
print "\tMemory Mapping..."
with open(fileName, "rb") as f:
map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
map.seek(channelNo*line_count*sample_count*arrayName.itemsize)
for i in xrange(line_count*sample_count):
arrayName[0, i] = unpack('>f', map.read(arrayName.itemsize))[0]
# Same method as above, just more verbose for the maintenance programmer.
# for i in xrange(line_count*sample_count): #row
# be_float = map.read(arrayName.itemsize) # arrayName.itemsize should be 4 for float32
# le_float = unpack('>f', be_float)[0] # > for big endian, < for little endian
# arrayName[0, i]= le_float
map.close()
return arrayName
print "Initializing the Amp HH HV, and Phase HH HV arrays..."
HHamp = np.ones((1, line_count*sample_count), dtype='float32')
HHphase = np.ones((1, line_count*sample_count), dtype='float32')
HVamp = np.ones((1, line_count*sample_count), dtype='float32')
HVphase = np.ones((1, line_count*sample_count), dtype='float32')
print "Ingesting HH_Amp..."
HHamp = mmapChannel(HHamp, 'ALPSRP042301700-P1.1__A.img', 0, line_count, sample_count)
print "Ingesting HH_phase..."
HHphase = mmapChannel(HHphase, 'ALPSRP042301700-P1.1__A.img', 1, line_count, sample_count)
print "Ingesting HV_AMP..."
HVamp = mmapChannel(HVamp, 'ALPSRP042301700-P1.1__A.img', 2, line_count, sample_count)
print "Ingesting HV_phase..."
HVphase = mmapChannel(HVphase, 'ALPSRP042301700-P1.1__A.img', 3, line_count, sample_count)
print "Reshaping...."
HHamp_orig = HHamp.reshape(line_count, -1)
HHphase_orig = HHphase.reshape(line_count, -1)
HVamp_orig = HVamp.reshape(line_count, -1)
HVphase_orig = HVphase.reshape(line_count, -1)
ich für jemand anderen dazu hinzufügen wollte, die diesen Beitrag nützlich findet. Das Ausführen des ursprünglichen Codes dauert ungefähr 80 Sekunden. Die Lösung von Alex Martelli und JF Sebastian läuft weniger als eine Sekunde. Das Programm, das diese Funktion aufruft, tut dies so oft. Die Laufzeit ist damit deutlich gesunken. Danke euch beiden für die Hilfe und dafür, mir etwas beizubringen =) – Foofy