Forum: Mikrocontroller und Digitale Elektronik Datei lesen


von chris (Gast)


Lesenswert?

Hallo zusammen,
 ich habe in einer Datei ein Paar Pakete in Ascii gespeichert:
"
Packet: 1
Daten:12345671234....
Paket: 2
Daten:12234324352435..
Paket: 3
Daten:1234123z4123..
"
ich kann auf die Datei zugreifen, wie kann ich dann wenn ich Z.B.: 1
eingebe nur die Daten von paket 1 hole, das gleiche für 2,3....,welche
Funktionen werde ich gebrauchen!!
vielen Dank für euer Tip

von André K. (freakazoid)


Lesenswert?

Häh? Ein wenig genauer wenn möglich.

Wo sind Dateien gespeichert?
Wer versucht zu lesen?
Welche Sprache?
...

Grüße, Freakazoid

von >-öööööööÄ> (Gast)


Lesenswert?

sind die Pakete von fester Länge oder aus den Daten zu erkennen?

von Karl H. (kbuchegg)


Lesenswert?

Das ist ganz einfach:
Du liest immer die komplette Datei und speicherst
nur das was du brauchst, alles andere überliest du.
d.h.

   solange ein Satz aus der Datei gelesen werden konnte {
     war es der vom gewünschten Packet?
     Ja: Super, lies den nächsten Daten-Satz und fertig
     Nein: mach nichts weiter, sondern ab in die nächste
           Schleifenwiederholung.
   }
   Packet konnte nicht gefunden werden -> Fehler

Das ganze ist wie bei den guten alten Audio-Kasetten
(nur dass du keinen Schnellen Vor- oder Rücklauf hast).
Die konnte man auch nur abspielen, bis das Lied am
Band auftaucht.

von >-öööööööÄ> (Gast)


Lesenswert?

und was macht dann fseek ?

von Karl H. (kbuchegg)


Lesenswert?

Wie bitte willst du fseek() in einer Textdatei sinnvoll
nutzen?

von Karl H. (kbuchegg)


Lesenswert?

das ist
  .. ohne ftell()

von Karl H. (kbuchegg)


Lesenswert?

zb. aus der VC++ Doku:

<Quote>

For streams opened in text mode, fseek has limited use,
because carriage return–linefeed translations can cause fseek
to produce unexpected results. The only fseek operations
guaranteed to work on streams opened in text mode are:

* Seeking with an offset of 0 relative to any of the origin values.
* Seeking from the beginning of the file with an offset value
  returned from a call to ftell.

</Quote>

Und soweit ich mich erinnern kann, entspricht das ganz genau dem,
was auch der C-Standard von fseek fordert.

von >-=====+> (Gast)


Lesenswert?


von chris (Gast)


Lesenswert?

die Datei ist in einem Ordner gespeichert, Sprache ist 'C'.
ok, mit fopen öffne ich meine Datei, habe gedacht mit fgets lese ich
die Zeilen,und mit sscanf suche ich nach Paket Nr und Daten und
speicher die in variablen!!!!!!!!!!
wie kann ich die ganzen "Daten" von Z-B. Paket:2 holen, auhc wenn da
ein Leerzeichen ist? und bei dem Anfang von Wort "Paket: 3" aufhören
zu suchen??
bin dankbar für FunktionsNamenempfehlungen,mit fseek versuche ich
gleich.

von Karl H. (kbuchegg)


Lesenswert?

@ >-=====+>

Nur mal kurz reingeschaut:
feof() ist (wie üblich) falsch benutzt.

feof() wird nicht benutzt um die Leseschleife abzubrechen.
Dazu wird immer ein Returnwert von der eigentlichen Lesefunktion
benutzt. Der sagt aus, ob das lesen gut ging oder nicht.
Ging der Lesevorgang nicht gut, bricht man die Schleife
ab und benutzt dann feof() um rauszufinden, was denn das Problem
war. Wenn es eof war, dann ist alles gut: die Datei ist
vollständig gelesen worden.

So wie es dort im Tutorial beschrieben wurde, lautet die
übliche Fragestellung in deviersen Newsgroups und Foren:
"Warum wird mein letzter Datensatz doppelt verarbeitet".

Traurig nur, dass dieses Tutorial von einem Professor
der Informatik verfasst wurde.

von >-=====+> (Gast)


Lesenswert?

nun hat der Chris ein erstes Rezept und die Korrektur dazu ....

von Karl H. (kbuchegg)


Lesenswert?

> ok, mit fopen öffne ich meine Datei, habe gedacht mit fgets lese
> ich die Zeilen,und mit sscanf suche ich nach Paket Nr und Daten
> und speicher die in variablen!!!!!!!!!!

Yep. so kann man das machen.

> wie kann ich die ganzen "Daten" von Z-B. Paket:2 holen,

Indem du vorher die Daten von Packet 1 liest.
Da du jeweils eine komplette Zeile fuer jeweils 'Packet'
bzw. 'Daten' reservierst ist das ja kein Problem.

Wenn du Packet #2 brauchst (und Deine Packete aufsteigend
durchnummeriert sind), musst du halt 2 mal mit fgets eine
komplette Zeile ( 1. Zeile für Packet1, 2. Zeile für Daten1)
lesen. Du machst halt nichts mit dem Gelesenem.

> auhc wenn da ein Leerzeichen ist? und bei dem Anfang von
> Wort "Paket: 3" aufhören zu suchen??

Das macht doch fgets von alleine. fgets liest eine komplette
Zeile ein. Da die Daten vom Packet 2 alle in einer Zeile
stehen, liest ein fgets die auch komplett ein.

von Unbekannter (Gast)


Lesenswert?

Also, erstmal öffnest Du die Datei im Binary-Mode. Scheiss auf den
Text-Mode, das bischen ASCII kannst Du auch so verarbeiten.

Auf Posix-Plattformen brauchst Du das "b" bei fopen sowieso nicht.
Aber Windows ist ja keine Posix-Plattform, sondern eine Krankheit. Was
Windows genau im Textmode macht, weiß ich nicht. Das muss jemand
anderes erklären.

Egal, im Binary-Mode öffen, also fopen(dateiname, "rb").

Wenn Du nun einen bestimmten Daten-Satz willst, musst Du eine
Binary-Suche machen. Der Trick besteht darin, nach jedem fseek() den
Anfang der aktuellen Zeile zu suchen. Wenn die aktuelle Zeile dann eine
Datenzeile ist, musst Du noch zur nächsten Packet-Zeile vorrücken. Du
musst nur etwas aufpassen, dass Dein Binary-Search nicht in eine
Endlosschleife gerät, durch das verschieben des File-Cursors.

Wenn Dir das alles zu kompliziert ist, geht's vielleicht auch viel
einfacher:

Wie groß ist denn die komplette Datei? Wenn nicht "zu" groß,
RAM-Speicher ist billig und virtueller Speicher noch billiger, lies
einfach die komplette Datei in den RAM.

Danach parst Du die Datei einmal, und legst Dir ein Array mit
Pointern auf den Begin der entsprechenden Datensätze im RAM an. Dann
brauchst Du beim Random-Access nicht jedes mal die kompletten Daten
durchsuchen (O(n^2)!!!).

Wenn Du es ganz komfortabel machen willst, liest Du die Datei nicht mit
fread() ein, sondern mappst sie in den Speicher. Unter Posix ist das
kein Problem, unter Windows, keine Ahnung.

Dazu machst Du dann einen Cache davor, der zu den einzelnen Datensätzen
den Offset speichert. Wenn Du nun einen Random-Access machst, schaust Du
erst nach, ob der Pointer schon im Cache ist. Wenn nein, machst Du ein
Binaray-Search auf die gemappte Datei und legst den Pointer für
zukünftige Zugriffe in den Cache ab.

von Karl H. (kbuchegg)


Lesenswert?

@ >-=====+>

Kennst Du den Mann?
Wenn ja, dann richte ihm bitte einen schoenen Gruss von mir
aus: Es herrscht in der C-Gemeinde die einhellige Meinung,
wer gets() in einem Tutorial empfiehlt, ohne auf die Gefahren
hinzuweisen, sollte sofort und ohne Umschweife direkt an
die Wand gest... werden. Zumindest hat er seine Glaubwürdigkeit
als C-Lehrer sofort zu 100% eingebüsst. Am besten kommt gets() in
einem C-Tutorial überhaupt nicht vor und seine Verwendung
wird unter Strafe gestellt.

http://www.wi-bw.tfh-wildau.de/~hendrix/grundstudium/c/skript/standardfunktionen.html

von Karl H. (kbuchegg)


Lesenswert?

> Was Windows genau im Textmode macht, weiß ich nicht. Das muss
> jemand anderes erklären.

Es findet lediglich die Umsetzung von 0x0D, 0x0A zu '\n'
beim Lesen, bzw. umgekehrt beim Schreiben statt.

Bei allem Respekt:
Aber das binary Suchen auf einer Datei ist für einen
Neuling schon etwas hart. Das kriegt er die nächsten
2 Monate nicht gebacken.
Gegen die Empfehlung eines Datensatz-Pointer-Caches ist
hingegen nichts einzuwenden.

> Danach parst Du die Datei einmal, und legst Dir ein Array
> mit Pointern auf den Begin der entsprechenden Datensätze im RAM an.

Naja. Pointer ist vielleicht der falsche Begriff, weil man
ihn mit dem RAM assoziert. Mir faellt aber auch kein Besserer
ein. Auf jeden Fall kriegt man die mit ftell().
(Und dann spielt es auch keine Rolle mehr ob man Textmode oder
Binary Mode benutzt).

von Andreas B. (Gast)


Lesenswert?

Also Windows hat bei meinen Test im ASCII Modus nur alle ASCII zeichen
gelesen, alle Zeichen die nicht im Bereich lagen waren (glaube ich) 0.
Könnte aber auch an den aktuellen Rechnern gelgen haben.

Dann weiter, wegen den Packeten, wenn die immer gleich lang sind kannst
du mit fseek an die richtige Stelle Springen, wenn du z.b. nach jedem
Packet ein '\n' hast kannst du diese Zählen.

mfg Andreas

von Unbekannter (Gast)


Lesenswert?

@Karl:

> Es findet lediglich die Umsetzung von 0x0D, 0x0A zu '\n'
> beim Lesen, bzw. umgekehrt beim Schreiben statt.

Vielen Dank für die Infos, wieder etwas gelernt.

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.