ich stehe momentan etwas auf den Schlauch. Es geht darum eine config datei unter Verwendung der Elm-chan FatFs lib von einer SD card einzulesen. Das funktioniert soweit auch gut. Diese config Datei besteht aus mehreren Zeilen, wobei jede Zeile einen Eintrag bildet (soweit alles normal). Ich lese sie Zeile für Zeile ein und werte den entsprechenden Eintrag aus. So weit, so schön. Jetzt möchte ich aber in dieser config Datei nach dem lesen bestimmte Zeichen überschreiben (damit ändert sich die Dateigröße ja nicht) um bestimmte Einträge nach dem Lesen als ungültig zu kennzeichnen. Wie stelle ich das am besten an? Datei erst zum lesen öffnen und später beschreiben? Wie bekomme ich den Pointer auf den aktuellen Eintrag? Kann man, während die Datei als R/W offen ist, gleichzeitig lesen und schreiben? Oder muß ich letztendlich doch die komplette Datei neu schreiben? Das würde halt jede Menge Buffer benötigen. uC ist ein LPC11U35. Das Ram könnte dazu reichen, aber gefallen tut mir das nicht. Irgendwie ist mir die komplette Vorgehensweise dabei nicht klar. Kann mir da mal jemand auf die Sprünge helfen?
Wie wäre es wenn Du einfach die Config Datei zeilenweise einliest, bearbeitest und dann in derselben Reihenfolge in eine neue Datei schreibst. So eine Vorgehensweise würde ein Minimum an SRAM beanspruchen. Die zu lesende Datei kann man nachher löschen. Wenn die Datei unter keinen Umständen beschädigt werden darf, vielleicht vorher noch eine Kopie anfertigen.
Hmm, die Grundidee ist gut. Dann müßte man die Datei unter einen anderen Namen speichern, das Original löschen und dann umbenennen. Das wäre halt relativ viel Geschreibe auf der Karte, aber wenn es anders nicht geht... Ein Punkt noch: Die Reihenfolge der Zeilen wäre egal. Falls noch Ideen kommen. ;-)
Andreas B. schrieb: > Jetzt möchte ich aber in dieser config Datei nach dem lesen bestimmte > Zeichen überschreiben (damit ändert sich die Dateigröße ja nicht) um > bestimmte Einträge nach dem Lesen als ungültig zu kennzeichnen. > Wie stelle ich das am besten an? > Datei erst zum lesen öffnen und später beschreiben? > Wie bekomme ich den Pointer auf den aktuellen Eintrag? f_seek(). > Kann man, während die Datei als R/W offen ist, gleichzeitig lesen und > schreiben? Kann sein.
Kannst Du nicht eine zweite Datei mit den gewünschten Änderungen Zeile für Zeile anfertigen, ohne die Originaldatei zu "beschädigen"? Bei Vorhandensein dieser zweiten Datei (z.B. mit anderer Endung) kann das System daraus ja die notwendigen Rückschlüsse ziehen und damit weitermachen bzw. wenn diese beschädigt ist aus der Orignialdatei eine Neue erzeugen.
Andreas B. schrieb: > Hmm, die Grundidee ist gut. Dann müßte man die Datei unter einen anderen > Namen speichern, das Original löschen und dann umbenennen. Ich weiß nicht, ob das bei dieser fat-Lib so geht, aber das übliche Pattern ist, die neue Datei als versteckte Datei im gleichen Verzeichnis anzulegen und nach dem Schreiben auf den Namen des Originals umzubenennen, aber ohne die vorher zu löschen. Das hat nämlich den Vorteil, dass das dann aus Dateisystemsicht eine atomare Operation ist. Es kann nicht vorkommen, dass zwischen dem löschen und dem umbenennen irgendwas passiert, das dazu führt, dass du ohne gültige Konfigurationsdatei da stehst. Falk B. schrieb: >> Kann man, während die Datei als R/W offen ist, gleichzeitig lesen und >> schreiben? > > Kann sein. Würde ich eigentlich erwarten. Wozu sonst sollte es einen Modus "R/W" geben?
Andreas B. schrieb: > Das wäre halt relativ viel Geschreibe auf der Karte, Du schreibst zuerst in eine Variable, und erst wenn Du fertig bist schreibst Du in die Datei.
Harald schrieb: > Kannst Du nicht eine zweite Datei mit den gewünschten Änderungen Zeile > für Zeile anfertigen, ohne die Originaldatei zu "beschädigen"? Das war ja die Idee von Gerhard. Aber es stimmt schon: Ich werde die alte Datei nicht löschen sondern umbenennen und dann die neu erzeugte auf den Original Namen umbenennen. Dann hätte man noch das Original falls was schief laufen sollte. Rolf M. schrieb: > Es kann nicht vorkommen, dass zwischen dem löschen und dem umbenennen > irgendwas passiert, das dazu führt, dass du ohne gültige > Konfigurationsdatei da stehst. Wenn ich das so mache wie eben beschrieben (nicht löschen), dann passiert das nicht.
Rolf M. schrieb: > Würde ich eigentlich erwarten. Wozu sonst sollte es einen Modus "R/W" > geben? Laut ChaNs Webseite kann die Library das. Wie das in der Praxis aussieht muss man mal schauen. f_seek() wurde ja schon genannt. So generell habe ich ein paar Bauchschmerzen wenn mit zeilenorientierten (Text?) Dateien gearbeitet wird, es aber feste Positionen in der Datei gibt. Ich würde statt dessen eine Binärdatei mit TLV-Aufbau verwenden https://de.wikipedia.org/wiki/Type-Length-Value und noch ein Valid-Flag (Bit oder Byte) einführen, das sagt ob der Eintrag gültig ist. Das Valid-Flag lässt sich kontrollierter setzen oder löschen als in einer Textdatei Daten überschreiben oder ausnullen.
Dosenfutter schrieb: > So generell habe ich ein paar Bauchschmerzen wenn mit zeilenorientierten > (Text?) Dateien gearbeitet wird, es aber feste Positionen in der Datei > gibt. Naja, es ist eine config Datei, die vom Anwender editiert werden soll. Das genannte f_seek positioniert lediglich auf eine Bytenummer, die erst mal gefunden werden muß. Solange das innerhalb des gleichen Blocks liegt ist es ja noch einfach. Dann wird es aber kompliziert. Ansonsten: Danke für die Tips. Ich habe es jetzt so umgesetzt: Datei wird normal gelesen. Falls ein diesbezüglicher Eintrag auftaucht wird ein Flag gesetzt. Am Schluss wird das Flag abgefragt und im gesetzten Fall die Datei nochmals Satz für Satz durchgegangen und die entsprechenden Einträge auf ungültig gesetzt. Das wird dann in eine neue Datei geschrieben. Abschließend werden beide Dateien umbenannt. Damit das Ganze nicht allzu geheimnisvoll aussieht: Bei den besagten Datensätzen handelt es sich um die Uhrzeit oder Zeitkorrektur für die RTC. Das soll halt nur einmal gesetzt werden, falls das Programm 2x gestartet wird. Dieser Eintrag sollte auch nur vorkommen, falls die RTC mal nicht (Batterie leer) oder falsch geht.
Andreas B. schrieb: > Damit das Ganze nicht allzu geheimnisvoll aussieht: Aber was hat das Ganze denn mit dem Thema Elm Chan FAT zu tun? Es ist doch nur ein Problem ob ich eine Datei zeilenweise oder zeichenweise behandle, und das sollte unabhängig vom verwendeten Dateisystem sein, sofern es einigermassen "vernünftig" implementiert ist, was man von dem beliebten Elm Chan FAT nun mal annehmen darf. Sonst hätte man davon schon längst was gehört.
the maverfehlung schrieb: > Aber was hat das Ganze denn mit dem Thema Elm Chan FAT zu tun? Jetzt nicht mehr. Ursprünglich wollte ich die Datei sowohl mit dem Read als auch mit dem Write Flag öffnen und dieses eine Zeichen überschreiben. Da kamen aber keine konkreten Tips dazu. So oft scheint diese Anforderung wohl doch nicht vorzukommen. Nochmal: Es ging um das Überschreiben eines chars in einer schon vorhandenen Textdatei.
Andreas B. schrieb: . > Jetzt möchte ich aber in dieser config Datei nach dem lesen bestimmte > Zeichen überschreiben (damit ändert sich die Dateigröße ja nicht) um f_seek() wurde ja schon genannt, du suchst dann in deiner config datei an welcher stelle das Zeichen steht und überschreibst das dann.
Andreas B. schrieb: > Datei erst zum lesen öffnen und später beschreiben? Wenn du immer überschreiben willst: Natürlich nicht, dann kannst du sie auch gleich RW öffnen. > Wie bekomme ich den Pointer auf den aktuellen Eintrag? Durch rechnen und seeken. Fies bei zeilenweiser Verarbeitung: Zeilenumbrüche haben keine definierte Länge. Können typisch ein oder zwei Bytes lang sein. Das erschwert das Rechnen ein wenig, wenn die eigenen Routinen nur mit den Zeileninhalten werkeln und das Handling der Zeilen irgendeinem anderen Software-Teil überlassen wird. Typisches Anfängerproblem... > Kann man, während die Datei als R/W offen ist, gleichzeitig lesen und > schreiben? Ja, klar. Das ist der Sinn dieses Modus.
c-hater schrieb: >> Wie bekomme ich den Pointer auf den aktuellen Eintrag? > > Durch rechnen und seeken. Soso, seeken. Klingt eher sick . . .
c-hater schrieb: > Durch rechnen und seeken. Das ist schon klar und auch nicht das Problem. Die Frage wäre gewesen: Funktioniert das bei dieser lib auch über alle Blöcke der Datei? Die können ja sonst wo liegen. f_lseek (nicht fseek) benötigt eine Position. Ist das jetzt die gleiche wie diejenige, die ich mit durchzählen der gelesenenen chars finde oder haut mir da die Blockverwaltung dazwischen? Was ich dazu letztendlich brauche ist ein Pointer, der konkret darauf zeigt, wo sich der Lesezeiger gerade befindet. Und das muß dann auch der gleiche sein, den ich bei f_lseek anwende. > Das erschwert das Rechnen ein wenig, wenn die > eigenen Routinen nur mit den Zeileninhalten werkeln und das Handling der > Zeilen irgendeinem anderen Software-Teil überlassen wird. Typisches > Anfängerproblem... Das hat mit Anfänger herzlich wenig zu tun. Die config Date wird von irgend jemanden auf die Karte geschrieben. Ob das jetzt mit CR oder CR/LF gemacht wird, ist im Prinzip ja auch egal, wenn der entsprechende String gesucht wird. Man kann sich ja vor dem Lesen des Satzes den Anfang merken und muß nicht rückwärts suchen. >> Kann man, während die Datei als R/W offen ist, gleichzeitig lesen und >> schreiben? > > Ja, klar. Das ist der Sinn dieses Modus. Das ist nicht klar. Es gibt bei dieser lib ein Flag zu schreiben und eins zum lesen beim Datei öffnen. So gesehen ist das kein expliziter Modus. Kann also sein oder auch nicht. Ich wollte eigentlich auch keine Allgemeinplätze als Antwort haben, sondern konkret was und wie das bei dieser lib funktioniert. Sorry, aber bis jetzt hatte ich von niemanden den Eindruck, daß er die Elm-chan lib konkret kennt (und damit meinte ich nicht: Irgendwann mal benutzt haben).
Andreas B. schrieb: > c-hater schrieb: >> Durch rechnen und seeken. > Das ist schon klar und auch nicht das Problem. Die Frage wäre gewesen: > Funktioniert das bei dieser lib auch über alle Blöcke der Datei? Die > können ja sonst wo liegen. Aber sicher! Das ist doch kein Bastelmurks sondern feinste Software vom Meister Chan persönlich! > f_lseek (nicht fseek) benötigt eine Position. Ist das jetzt die gleiche > wie diejenige, die ich mit durchzählen der gelesenenen chars finde Sicher, das ist die Byteposition in der Datei! > oder > haut mir da die Blockverwaltung dazwischen? NEIN! > Das ist nicht klar. Es gibt bei dieser lib ein Flag zu schreiben und > eins zum lesen beim Datei öffnen. So gesehen ist das kein expliziter > Modus. Kann also sein oder auch nicht. Es ist so. > Ich wollte eigentlich auch keine Allgemeinplätze als Antwort haben, > sondern konkret was und wie das bei dieser lib funktioniert. Sorry, aber > bis jetzt hatte ich von niemanden den Eindruck, daß er die Elm-chan lib > konkret kennt (und damit meinte ich nicht: Irgendwann mal benutzt > haben). Ich hab sie benutzt, wenn gleich das schon ne Weile (tm) her ist und ich keinen RW Modus benutzt habe. RTFM! http://elm-chan.org/fsw/ff/doc/open.html
1 | FA_READ Specifies read access to the file. Data can be read from the file. |
2 | FA_WRITE Specifies write access to the file. Data can be written to the file. Combine with FA_READ for read-write access. |
Falk B. schrieb: >> Kann man, während die Datei als R/W offen ist, gleichzeitig lesen und >> schreiben? > > Kann sein. Falk B. schrieb: >> Das ist nicht klar. Es gibt bei dieser lib ein Flag zu schreiben und >> eins zum lesen beim Datei öffnen. So gesehen ist das kein expliziter >> Modus. Kann also sein oder auch nicht. > > Es ist so. Aha. Falk B. schrieb: > Ich hab sie benutzt, wenn gleich das schon ne Weile (tm) her ist und ich > keinen RW Modus benutzt habe. Eben. ;-) Das war ja meine Hoffnung, daß jemand genau das schon einmal mit dieser lib gemacht hat. Aber ich glaube Dir jetzt mal, daß das so funktioniert und werde es bei Gelegenheit mal testen.
Also, ich habe mich jetzt mal dran gemacht. Vorneweg: Es funktioniert prima und auch recht simpel (meine Hochachtung vor dem großen Meister Elm chan): - Datei mit flags FA_READ | FA_WRITE öffnen. - Vor jedem f_gets aus dem File Object den fptr auslesen und nach START speichern (der zeigt genau auf das n. Zeichen der Datei). - Satz mit f_gets lesen - fptr sichern (zeigt jetzt auf die nächste Zeile) - Dann den Offset des überschreibenden chars zu den gespeicherten fptr aus START addieren und damit (in fptr) dann f_putc aufrufen. - gesicherten fptr zurück in die Struktur und wieder von vorn bis Dateiende. - Datei schließen und alles ist so wie es sein soll. Und den ganzen Block Kram vergessen. Der große Meister kümmert sich drum. ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.