Lesen eine ganze binäre Datei in Python
Muss ich import binäre Datei von Python -- die Inhalte sind signed 16-bit Integer big endian.
Den folgenden Stack-Überlauf Fragen schlagen, wie Sie ziehen in mehrere bytes zu einer Zeit, aber ist dies der Weg, um scale-up zu Lesen, in eine ganze Datei?
Dachte ich, so eine Funktion zu erstellen wie:
from numpy import *
import os
def readmyfile(filename, bytes=2, endian='>h'):
totalBytes = os.path.getsize(filename)
values = empty(totalBytes/bytes)
with open(filename, 'rb') as f:
for i in range(len(values)):
values[i] = struct.unpack(endian, f.read(bytes))[0]
return values
filecontents = readmyfile('filename')
Aber das ist ziemlich langsam (die Datei ist 165924350 bytes). Gibt es einen besseren Weg?
- Ich denke, es ist langsam, weil der
bytes=2
. - Lesen eine 150mb-Datei ist, wird langsam sein. Was erwarten Sie? Wie langsam ist es?
- Es ist tatsächlich nur etwa 3,5 Minuten (je nach unix -
time
), aber Lesen kann ich es in R in weniger als einer minute mitreadBin
- (und ich habe Tausende von diesen Dateien...)
- Sind die Daten eindeutig Binär-oder das ASCII-Darstellung 16-bit-zahlen?
- ASCII-Repräsentationen, denke ich...
- In UNIX, Typ
head [filename]
Wenn Sie Lesen können, die umbers, müssen Sie ASCII-oder andere text-vs "binary". - Ja-das ist, was ich getan hatte und ich konnte sehen, wie die x\215l... also ich würd davon ausgegangen, es war die ASCII-Darstellung? Das etwas ändert?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde direkt Lesen, bis ein EOF-Zeichen (es bedeutet die überprüfung für das empfangen von einer leeren Zeichenkette), entfernen Sie dann die Notwendigkeit der Verwendung von range() und getsize.
Alternativ können Sie
xrange
(stattrange
) sollten die Dinge verbessern, vor allem für die Speichernutzung.Außerdem ist, wie Falmarri vorgeschlagen, Lesen mehr Daten in der gleichen Zeit, die Verbesserung der Leistung eine ganze Menge.
Sagte, ich würde keine Wunder erwarten, auch weil ich nicht sicher bin, eine Liste ist die effizienteste Art und Weise zu speichern, dass die Menge der Daten.
Was über die Verwendung von NumPy-Array und seine Einrichtungen zu Lesen/schreiben von Binärdateien? In diesem link gibt es einen Abschnitt zum Lesen von raw-binary-Dateien, mit numpyio.fread. Ich glaube, das sollte genau das sein, was Sie brauchen.
Hinweis: ich persönlich habe noch nie verwendet NumPy; jedoch, seine wichtigsten raison d ' etre ist genau die Handhabung von großen Mengen von Daten - und das ist, was du tust, in deiner Frage.
Verwenden
numpy.fromfile
.fromfile(filename,dtype='>i2')
?Den Sie gerade Lesen, ein-und Auspacken von 2 Byte zu einem Zeitpunkt
Warum nicht Sie Lesen sich wie, 1024 Byte zu einem Zeitpunkt?
TypeError: Struct() argument 1 must be string, not int
Hatte ich die gleiche Art von problem, obwohl in meinem speziellen Fall musste ich das konvertieren eine sehr seltsame Binär-format (500 MB) Datei mit interlaced-blocks 166 Elemente, die 3-Byte-Ganzzahlen mit Vorzeichen; also ich habe auch das problem der Umwandlung von 24-bit auf 32-bit-Ganzzahlen mit Vorzeichen, dass die Dinge verlangsamen ein wenig.
Ich habe es behoben mit NumPy ist memmap (es ist nur eine praktische Möglichkeit der Verwendung von Python ist memmap) und struct.entpacken auf großen chunk der Datei.
Mit dieser Lösung bin ich in der Lage zu konvertieren (Lesen, Dinge zu tun, und schreiben auf die Festplatte) die gesamte Datei in über 90 Sekunden (zeitgleich mit der Zeit.clock()).
Ich hochladen könnte Teil des Codes.
Ich denke, dass der Engpass, die Sie hier haben, ist eine doppelte.
Je nach OS-und Disk-controller, die Anrufe zu
f.read(2)
mitf
ein bigish-Datei sind in der Regel effizient gepuffert -- in der Regel. In anderen Worten, das Betriebssystem wird das Lesen von einem oder zwei Sektoren (mit disc-Sektoren in der Regel mehrere KB) off disc in den Speicher, da dieser nicht viel teurer ist als das Lesen von 2 bytes aus dieser Datei. Die extra-bytes zwischengespeichert werden effizient im Speicher bereit für den nächsten Anruf zu Lesen, dass die Datei. Verlassen Sie sich nicht auf dieses Verhalten-es könnte dein Flaschenhals-aber ich denke, es gibt andere Probleme hier.Ich bin mehr besorgt über die single-byte-Konvertierungen, um eine kurze und einzelne Aufrufe numpy. Diese werden nicht zwischengespeichert überhaupt. Behalten Sie alle shorts in eine Python-Liste von ints und konvertieren die ganze Liste zu numpy, wenn (und falls) nötig. Sie können auch einen einzelnen Anruf
struct.unpack_from
alles zu konvertieren in einem Puffer vs einer kurzen zu einer Zeit.Betrachten:
Ich habe eine Datei von random shorts signed ints von 165,924,350 bytes (158.24 MB) die comports zu 82,962,175 signed 2 byte shorts. Mit dieser Datei, lief ich in den
read_wopper
- Funktion oben und es lief in:Wenn Sie nicht müssen die shorts werden numpy, diese Funktion läuft in 6 Sekunden. All dies auf OS X, python 2.6.1 64 bit, 2.93 gHz Core i7, 8 GB ram. Wenn Sie ändern
buf_size=1024*2
imread_wopper
zubuf_size=2**16
die Laufzeit ist:Also Ihre Haupt-Flaschenhals ist, denke ich, die single-byte ruft zum entpacken -- nicht Ihre 2 byte liest von der CD. Möchten Sie vielleicht, um sicherzustellen, dass Ihre Daten-Dateien nicht fragmentiert und wenn Sie mit OS X, dass Ihr free disc space (und hier) nicht fragmentiert.
Bearbeiten ich veröffentlicht den vollständigen code zu erstellen, dann Lesen Sie eine binäre Datei mit int-Werten. Auf meinem iMac, das ich konsequent get < 15 Sekunden zum Lesen der Datei mit zufälligen int-Werten. Es dauert etwa 1:23 zu schaffen, da die Schöpfung ist eine kurze, in einer Zeit,.
2m28s
Gesamtzeit vs1m33s
auf meinem system. Ich schrieb gerade etwas quick and dirty zu erstellen der Datei aus und schreibt 1, kurz, zu einer Zeit. Noch wichtiger:read_wopper
nimmt28.5s
zu Lesen und zu konvertieren, um ein numpy-array vs15.0s
auf meinem system. Der Unterschied ist wohl Speicher und eine neuere, schneller, leerer disc auf meinem sys. Ihr könnt ihn schneller durch die Erhöhung derbuf_size
zu einer größeren Anzahl und stellen Sie sicher, dass die Datei nicht fragmentiert ist. Mitbuf_size=2**16
- read_wopper Funktion nimmt10.8s
. Wie lange dauert dienumpy.filefrom
nehmen?105/110 GB filled up...
: Ja, das Problem in mehr als einer Hinsicht!numpy.filefrom takes only 0m6.458s
: Das ist deine Lösung! cheerio ;-]]