Forum: PC-Programmierung C++ Datei als Short int array einlesen.


von Philipp K. (philipp_k59)


Lesenswert?

Hi,

ich habe eine Datei mit Farbinformationen als Bin mit theoretisch immer 
aufeinander folgenden 2Bytes als "unsigned short int".

Im moment lese ich mit gseek immer 2 Bytes ein, konvertiere die 2Bytes 
zu einem Short Int und schiebe die nacheinander wie in der Datei 
sortiert in ein Array.

Das einlesen dauert mit 2MB von der SD-Card eben mal 30-60Sekunden.

Zuerst dachte ich das es am besten ist die Ganze Datei als char Array 
mit großem Buffer einzulesen und dann das casten zu starten.

Dann habe ich ähnliches mit float und Vector gesehen wo das irgendwie in 
einem Rutsch geht, nur verstehe ich die ganze Geschichte dahinter nicht.

Andere Idee,vielleicht liegen die Bytes schon richtig und können sogar 
direkt gemapped werden.

Was wäre denn jetzt die Sinnvollste Methode?

: Bearbeitet durch User
von Sebastian V. (sebi_s)


Lesenswert?

Philipp K. schrieb:
> Im moment lese ich mit gseek immer 2 Bytes ein

Meinst du seekg? Damit kann man gar nichts einlesen sondern nur die 
Position setzen wo man als nächstes lesen will. Wenn man aber alles 
nacheinander lesen will ist das überhaupt gar nicht nötig. Du kannst 
einfach mit read 
(http://en.cppreference.com/w/cpp/io/basic_istream/read) immer 2 Bytes 
laden und die Position wird automatisch 2 Bytes weiter gesetzt.

Ob du erst alles einließt und dann konvertierst oder beim Einlesen 
konvertierst sollte ziemlich egal sein. Zeig mal deinen Code.

von Peter II (Gast)


Lesenswert?

Welche Plattform?

und was ist gseek?

Zeige uns doch mal den Code, wie du es gemacht hast.

von Philipp K. (philipp_k59)


Lesenswert?

Ah sorry, bin da noch nicht solang mit c++ das ich alles im Kopf habe, 
seekg klar, wenn man english kann leuchtets ein also ich meinte Read.

Verstanden habe ich die Sache schon soweit das ich den Copy&Paste Code 
schon für mich angepasst habe. Der war vorher um ein BMP einzulesen..

Mir geht es nur darum das Read durch einen kleinen Buffer im folgenden 
Code zu langsam sein müsste.
1
   file.seekg (0, file.end);
2
        size = file.tellg();
3
        matrix= new(unsigned short int[size/2]);
4
        sof=0;
5
        int counter=0;
6
        while(sof<size)
7
        {
8
            file.seekg(sof,ios::beg);
9
            file.read(tmp,2);
10
            tx = BinToNum(tmp,2);
11
            matrix[counter] = tx;
12
            sof+=2;
13
            counter++;
14
        }

EDIT: Wodran ich gerade hänge:
1
vector<unsigned short int> buffer(size);
2
if (file.read(buffer.data(), size))
3
{}

: Bearbeitet durch User
von A. Horn (Gast)


Lesenswert?

Es sollte etwas in der folgenden Art gehen:
(nicht getestet, nur so als Idee, seekg: nie benutzt...)

        file.seekg (0, file.end);
        size = file.tellg();
        matrix= new(unsigned short int[size/2]);
        file.seekg(0,file.begin);
        file.read(matrix,(size/2) * sizeof(unsigned short int));

Vielleicht hast du aber dann noch Endian-Problem...

von A. Horn (Gast)


Lesenswert?

Siehe auch
http://www.cplusplus.com/reference/istream/istream/seekg/
und das Beispiel auf der Seite

von Philipp K. (philipp_k59)


Lesenswert?

A. Horn schrieb:
> Vielleicht hast du aber dann noch Endian-Problem...

Danke, das Endianproblem kann ich Notfalls im File ändern.. Das sieht 
schonmal so aus wie es mir nicht in den Sinn gekommen ist.

EDIT: Schade, das macht zeitlich keinen unterschied.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Philipp K. schrieb:
> Ah sorry, bin da noch nicht solang mit c++ das ich alles im Kopf habe,
> seekg klar, wenn man english kann leuchtets ein also ich meinte Read.
>
> Verstanden habe ich die Sache schon soweit das ich den Copy&Paste Code
> schon für mich angepasst habe. Der war vorher um ein BMP einzulesen..
>
> Mir geht es nur darum das Read durch einen kleinen Buffer im folgenden
> Code zu langsam sein müsste.
>    file.seekg (0, file.end);
>         size = file.tellg();
>         matrix= new(unsigned short int[size/2]);

new ist keine Funktion, also lass die Klammern weg:

         matrix= new unsigned short int[size/2];

>         sof=0;
>         int counter=0;
>         while(sof<size)
>         {
>             file.seekg(sof,ios::beg);
>             file.read(tmp,2);
>             tx = BinToNum(tmp,2);
>             matrix[counter] = tx;
>             sof+=2;
>             counter++;
>         }

Das läßt sich evtl. schon deutlich beschleundigen, wenn du den seekg 
wegmachst. Den brauchst du sowieso nicht.

von Sebastian V. (sebi_s)


Lesenswert?

Rolf M. schrieb:
> Das läßt sich evtl. schon deutlich beschleundigen, wenn du den seekg
> wegmachst. Den brauchst du sowieso nicht.

Er braucht es genau zweimal. Einmal um ens Ende der Datei zu springen 
und dann wieder zurück an den Anfang. Die restlichen in der Schleife 
sind total unnötig.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn die Bytes in der Datei in der korrekten Reihenfolge abgelegt sind, 
dann geht auch so etwas:
1
file.seekg(0, file.end);
2
size = file.tellg();
3
matrix = new uint16_t[size / 2];
4
5
file.seekg(sof,ios::beg);
6
file.read((uint8_t *) matrix, size);

Das geht nur dann schief, wenn aus Alignmentgründen die 16-Bit-Werte 
nicht ohne Lücken im Speicher abgelegt werden können, was manche 
32-Bit-Architektur möglicherweise machen könnte.

Das lässt sich mit dem sizeof-Operator prüfen, wie groß ist ein Array 
aus zwei uint16_t? Doppelt so groß wie ein einzelner uint16_t?

von Klaus W. (mfgkw)


Lesenswert?

Aus der Entfernung siegt es danach aus, als ob es mit "memory mapped 
file" deutlich schneller ginge (mmap()).

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Klaus W. schrieb:
> als ob es mit "memory mapped file"

Kommt ganz drauf an, was für ein Betriebssystem und was für eine 
Hardware hier verwendet wird. Das hat der Threadstarter für sich 
behalten, auch wenn man vermuten kann, daß es hier um ein Programm auf 
einem PC geht.

Allerdings: Warum sollte ein "memory mapped file" hier schneller sein 
als ein einziger Aufruf von read()? Was glaubst Du, macht ein "memory 
mapped file" anderes?

von Klaus W. (mfgkw)


Lesenswert?

so wie ich das verstanden habe, geht es nicht darum, einmal 2 Byte 
anzufassen, sondern oft hintereinander (sonst würde er die Lesezeiten ja 
gar nicht merken).
Und das geht nach meiner Erfahrung mit mmap meist dramatisch schneller.

Hatten wir nicht schon mal diese Diskussion?

(Ein AVR wird es nicht sein, wenn er mit seekg hantiert.)

von Peter II (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Was glaubst Du, macht ein "memory
> mapped file" anderes?

es kopiert nicht dem Speicher 2 mal. Es fallen damit ein paar 
Kontextwechsel zwischen Kernel und Userspace weg.

von Klaus W. (mfgkw)


Lesenswert?

Rufus Τ. F. schrieb:
> Allerdings: Warum sollte ein "memory mapped file" hier schneller sein
> als ein einziger Aufruf von read()? Was glaubst Du, macht ein "memory
> mapped file" anderes?

Wenn der Inhalt einer Datei bzw. eine Seite davon erstmal in den 
Speicher eingeblendet ist, geht der Zugriff über einen Pointer darauf 
wesentlich schneller, einfach weil nichts kopiert werden muß und 
keinerlei Bibliotheksfunktionen bemüht werden.

von Philipp K. (philipp_k59)


Lesenswert?

Danke für die vielen Tips :)

Also da ist kein Geheimnis denn es ist ein RPi und die Datei liegt auf 
der sdcard vom System.

Die Bin Datei beinhaltet ganze Font Zeichensätze die ich selbst gemalt 
habe um Headless in einen SPI-Buffer zu schreiben.. das funktioniert 
schonmal mit 25fps und da verschiebe ich den ganzen matrix array mit for 
Schleifen bei jedem einzelbild. Also im ganzen dauert mir das Laden der 
Datei zu lang beim Debuggen, wenn ich die Daten direkt ins Headerfile 
schmeisse mault der RPi beim Kompilieren Speicher voll. Ich finde es 
trotzdem interessant den richtigen Ansatz zu finden.

Hier mal mein wie soll ich sagen.. schauen obs klappt dann mach ichs 
schick  Workaround File:

http://bit.do/philipp_k

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.