Datensatz-Datei auslesen
-
Guten Morgen,
ich hoffe ich bin mit meiner Frage hier an der richtigen Stelle
Meine Frage betrifft das Auslesen von einer Datendatei in einem gewissen Format.Ein Freund von mir hat gefragt ob ich eine Datei (in C) auslesen kann, welches folgendes Format hat.
Länge: int16
[432][432]...[432]Kurz zur Erklärung.
Er hat einen kleinen Scanner gebaut, welcher die Daten der Detektoren in einer Datendatei speichert. Diese hat das Format wie oben. Es sind X "Datensätze" die jeweils aus Y "Daten" vom Typ in16 bestehen.
X sind quasi die "Zeilen" der Aufnahme
Y sind die "Reihen"Nehmen wir mal an X=500 und Y=432 macht ein Bild von 432*500. Das macht nun 432 Werte von Typ int16, dann kommen weitere 432 Werte von Typ int16 (welche nun die zweite Zeile darstellen.
Nun stellt sich die Frage, wie ich die Datei öffnen und auslesen kann. Ich habe es mit folgenden Code probiert:#include <stdio.h> #include <stdlib.h> int main(void) { int i, k, z, y; FILE *datei_mess; unsigned short puffer[432]; datei_mess=fopen("test.dat", "r"); for (y=0; y<=431; y=y+1) { puffer[y]=0; } if (datei_mess!=NULL) { //fread(&puffer, sizeof(unsigned short), 1, datei_mess); //Eingabe der Werte for (i=0; i<=431; i=i+1) { fscanf(datei_mess, "%d" , &puffer[i]); } fclose(datei_mess); for (k=0; k<=431; k=k+1) { printf("%d Wert %i \n",k+1, puffer[k]); } printf("\n"); } else { puts("Dateien konnten nicht geöffnet werden!"); } return EXIT_SUCCESS; }
Ihr seht den Quellcode ist nicht gerade lang und ich denke auch die Aufgabe ist nicht schwer. Es soll die Datei erst mal nur ausgeben werden (Console). Leider kann ich die Ausgabe nur schlecht überprüfen, weil wenn ich die Datei öffne nur Hieroglyphen sehe
Eine Ausführung wirf mir aber für alle Werte 0 aus.Eventuell hat ja einer eine zündende Idee.
Danke schon mal!
-
Pinockel schrieb:
Leider kann ich die Ausgabe nur schlecht überprüfen, weil wenn ich die Datei öffne nur Hieroglyphen sehe
Das deutet darauf hin, dass die Daten binär abgespeichert sind. Da kommst du mit fscanf nicht weiter.
int16_t puffer[432]; // dafuer brauchst du #include <stdint.h> .... fread( puffer, sizeof(puffer[0]), 432, datei_mess); // ^kein Adressoperator bei Arrays
Das fread ersetzt deine komplette Leseschleife (Zeilen 21-24)
Wobei du da wohl noch am Anfang die Länge überlesen musst.
So ganz schlau werde ich nicht aus der Beschreibeung der Datei.
-
danke für deine Antwort
Ich versuche es noch mal etwas genauer auszudrückenEs ist im Prinzip ein Datenstrom. Der Scanner hat 432 Detektorpixel. Ein Pixel wird in einem Wert vom Typ int16 abgespeichert.
Somit wären die ersten 432 Werte die erste Zeile. Danach fährt der Scanner ein Stück runter und scannt erneut. Somit sind die die Wert 433 - 864 die 2. Zeile auf dem Bild und immer so weiter. Insgesamt bewegt sich der Scanner 500mal und Somit kommt man dann auf das Bild von 432*500 Pixeln.
-
int16_t puffer[500][432]; if( 1 == fread( puffer, sizeof(puffer), 1, datei_mess ) ) puts("OK"); else puts("Fehler");
Die Byteorder für int16 deines Scanners und deines C-Compilers müssen auch übereinstimmen.
-
Wutz schrieb:
int16_t puffer[500][432]; if( 1 == fread( puffer, sizeof(puffer), 1, datei_mess ) ) puts("OK"); else puts("Fehler");
Die Byteorder für int16 deines Scanners und deines C-Compilers müssen auch übereinstimmen.
Habe ich eingefügt und es sagt "OK", aber nun muss ich ja das einlesen wieder anpassen, da ich ja nun ein 2D Array habe?!
-
Pinockel schrieb:
... aber nun muss ich ja das einlesen wieder anpassen, da ich ja nun ein 2D Array habe?!
Das ist das einlesen.
Und du hast jetzt das ganze Bild im Speicher - und ja, es ist ein 2D-Array.
In deinem Beispielcode hast du ja nur eine Zeile eingelesen.
-
Okay hab es mal so probiert
if (datei_mess != NULL) { if (1 == fread(puffer, sizeof(puffer), 1, datei_mess)) puts("OK"); else puts("Fehler"); fclose(datei_mess); for (zeile = 0; zeile <= 499; zeile++) { for (reihe = 0; reihe <= 431; reihe++) printf("%d ", puffer[zeile][reihe]); printf("\n"); } } else { puts("Dateien konnten nicht geöffnet werden!"); }
Kann es sein, dass die Console ein Ausgabe-Limit hat?
Eigentlich müsste ja das "OK" oben links stehen
-
Pinockel schrieb:
Kann es sein, dass die Console ein Ausgabe-Limit hat?
Ja, kann sein.
Wo das liegt, hängt vom System ab.
Bei Windows kannst du es unter (Rechtclick auf das schwarze Symbol links in der Titelzeile) Eigenschaften->Layout einstellen.
-
Du kannst aber auch die Ausgabe mit > in eine Datei umlenken.
Programmname > test.out
-
Ach danke. Ich programmiere unter openSuse mit Eclispe, dort konnte ich den Punkt in den Einstellungen finden.
Ich habe das Programm nun etwas von der Ausgabe her verschönert und mir die Ergebnisse angesehen.
if (datei_mess != NULL) { fread(puffer, sizeof(puffer), 1, datei_mess); fclose(datei_mess); printf("Zeile\t"); for (k=0; k<=431; k++) printf("%d\t", k+1); printf("\n\n"); for (zeile = 0; zeile <= 499; zeile++) { printf("%d\t\t", zeile+1); for (reihe = 0; reihe <= 431; reihe++) { printf("%d \t", puffer[zeile][reihe]); } printf("\n------------------------------------------------------------------------------------------------------------------\n"); } } else { puts("Dateien konnten nicht geöffnet werden!"); }
Im Prinzip nur ein kleiner Tabellenkopf und eine lfd Nummer für die einzelnen Pixel. Sieht an sich gut aus, aber ein kleines Problem gibt es dennoch, aber ich glaube das hat etwas mit der Verschiebung zu tun.
Ich habe hier ein Bild von meinem Freund liegt inkl. x-y Achsen.Die Datei die ich einlesen gehört auch zu diesem Bild.
Sein Bild fängt eigentlich bei ungefähr bei Zeile 75 an (vorher nur ganz kleine Werte, weil das Objekt zu klein ist). Von oben gemessen natürlich.Laut meiner Tabelle, fängt das Bild aber erst bei Zeile 96 an. Ich hänge mal einen Auszug meiner Ausgabe an.
Zeile/Spalte 1 2 3 4 1 4095 4095 4095 4095 2 175 148 112 127 3 165 152 116 130 . . . 94 269 278 240 191 ... 95 657 524 485 541 ... 96 2384 1292 1108 1101 ... 97 3481 1899 1710 1542 ... . . ###BILD### . . 468 2348 2215 2184 1988 .... 469 1327 1090 1058 1060 ... 470 328 361 282 284 ...
Eventuell versteht ihr nun mein Vorhaben sogar noch besser
Ein Fehler könnte sein, dass die 1. Zeile nicht stimmen kann. Dort sollten wie bei Zeile 2 eigentlich auch recht kleine Werte stehen. Bei Zeile 95 sieht man, dass die Wert sprunghaft steigen (Anfang der Bildes). Das sollte aber eigentlich um Zeile 75 geschehen.
Das Ende ist ach verschoben. Ende laut Diagramm um Zeile 425 rum, aber bei mir erst bei Zeile 470Danke für eure tolle Hilfe bis jetzt
-
Überprüf erstmal mal die Größe der Datei 500x432x2 = 432000 Byte.
Wenn die Datei eine andere Größe hat, dann stimmt deine Annahme über den Aufbau der Datei nicht.Dafür spricht auch, dass das Objekt 350 Zeilen belegen soll, bei dir sind es 375.
Du musst schon deinen Freund fragen, wie das richtige Format ist.
Sch dir die Datei mit einem HEx-Viewer/Editor an.
Mit Irfan-View kann man auch Bild-Dateien im Raw-Modus öffnen.
Damit kannst du dir das auch mal anzeigen lassen.
(Ok, das ist für Windows, welches Programm das unter Linux kann, weiß ich leider nicht)
-
Danke für deine Antwort.
a) Bild habe ich leider keins da, sondern nur ausgedruckt auf einem Stück Papier.
b) Die Mess-Datei hat die Größe von 412,0 MiB (432 000 000) laut Linux DateimanagerAlso dann haut mit der Größe wirklich irgendwas nicht hin! Der Sache werde ich auf den Grund gehen.
Danke und ich melde mich noch einmal!
-
zu a)
Die Datei ist doch das Bild.
Bei einem RAW-Bildbetrachter kannst du 16Bit Graustufenbild mit 432 Spalten und 500 Zeilen einstellen.
Dann solltest du das Bild sehen.
Wenn das Bild versetzt ist (rechts/links), dann hast du einen Offset(Header) vorm Bild.
Verläuft das Bild diagonal, dann hast du die falsche Spaltenzahl.zu b)
1000 mal mehr ist schon merkwürdig.
Oder ist das eine Bilderreihe (Film)?
-
a) Jo genau. Hab auch gerade erfahren, dass es eine Bild-Reihe ist. Es sind wohl 1000 Bilder in der Datei. Sollte aber erst mal keine große Rolle spielen
b) Er meinte er hat einen Offset. Finde ich aber noch genau raus, wie ich da die Verschiebung hin bekomme. Die Werte vom Objekt hauen aber so wie es ausschaut erst mal hin. Immer lustig für andere Projekte zu programmieren
c) Die Datei bekomme ich mit IrfanView leider nicht auf. "Out of Memory" ... scheint wohl etwas zu groß sein, das Bild um es als RAW zu öffnen.
-
Hallo,
bin nun schon viel weiter und dafür schon mal vielen Dank für eure Hilfe!
Wieder ne kleine Randfrage:
Ich habe 9 Dateien die fast gleich heißen bspw. BLA_X.dat. Das X ist eine Variable die sich ändert. Ich möchte diese nun nach einander einlesen. Dafür ist natürlich eine Zählschleife ausgezeichnet. Dazu muss ich ja den fopen-Pfad irgendwie variabel machen. Ist sowas möglich?
-
Schau dir mal sprintf an: http://www.cplusplus.com/reference/cstdio/sprintf/
int X = 0; char dateiname[260]; // Für die 260 gibt es in irgendeinem Header auch eine Konstate/Makro ... sprintf(dateiname, "BLA_%d.dat", X); datei_mess=fopen(dateiname, "r");
-
Super Danke dir!
-
Das sowieso überall die 9 auftaucht, kannst du für das in auch
FILE *in[9];
nehmen. Dann aber ohnecalloc
.Dann klappt es auch mit fopen und fread.
Da das FileOpen ein int als Handle zurück gibt, bin ich mir nicht sicher, ob das überhaupt etwas mit C++ zu tun hat.
-
"Er" verwendet wahrscheinlich int-Handles für den Dateizugriff, in reinem C gibts aber nur FILE* dafür (in POSIX kann man FILE* auf int wandeln und statt fopen/fread/fwrite dann open/read/write benutzen), könnte z.B. dann so aussehen:
unsigned char werte[24]; FILE *in[9]; ... //setzen auf die Dateinamnen for(i=0;i<9;i++) { in[i]=fopen(dateiname,"rb"); /* binär ist wichtig */ } ... //Code fürs einlesen for(j=0;j<9;j++) { for(k=0;k<6;k++) { if( 1 == fread(werte,24,1,in[j]) )
-
Es ist etwas kompliziert, da er nachdem er die Dateien gelesen hat, noch etwas Daten verschieben muss, damit er die Werte korrekt im Rechner hat. Leider habe ich dazu (noch) keinen Code gefunden.
Er erstellt mir zwar eine Datei und schreibt auch Werte rein, die stimmen sollten, aber leider nicht genug. Wenn man sich die Datei anschaut, dann sieht es so aus, als ob dort nur die Werte von einer Quell-Datei gelesen und anschließend geschrieben werden.