Il a récemment demandé how to do a file slurp in python, et la réponse acceptée a suggéré quelque chose comme:Python fichier Slurp w/conversion endian
with open('x.txt') as x: f = x.read()
Comment pourrais-je faire de manière à lire le fichier et convertir la représentation endian du Les données? Par exemple, j'ai un fichier binaire de 1 Go qui est juste un tas de flottants de précision simple emballés comme un gros boutiste et je veux le convertir en little endian et dump dans un tableau numpy. Voici la fonction que j'ai écrite pour accomplir ceci et un vrai code qui l'appelle. J'utilise struct.unpack
faire la conversion endian et essayé d'accélérer tout en utilisant mmap
. Puis-je utiliser le slurp correctement avec mmap
et struct.unpack
? Y a-t-il un moyen plus propre et plus rapide de faire cela? En ce moment j'ai ce que j'ai, mais j'aimerais vraiment apprendre comment faire mieux.
Merci d'avance!
#!/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)
Je voulais ajouter à cela, pour quelqu'un d'autre qui trouve ce poste utile. Exécution du code d'origine que j'avais avait environ 80 secondes. L'exécution de la solution fournie par Alex Martelli et J F Sebastian est inférieure à une seconde. Le programme qui appelle cette fonction le fait plusieurs fois. En tant que tel, le temps de fonctionnement a considérablement diminué. Merci à vous deux pour l'aide et pour m'apprendre quelque chose =) – Foofy