Schreiben Sie eine zirkuläre Datei in c++
Schreiben brauche ich eine zirkuläre Datei in c++. Das Programm schreibt Zeilen in eine Datei und wenn der code erreicht eine maximale Anzahl der Zeilen, muss Sie überschreiben die Zeilen am Anfang der Datei.
Jemand eine Idee?
- warum brauchen Sie, um diese umzusetzen? was wirkliche problem versuchen Sie zu lösen?
- Muss ich schreiben, Listen von Bezeichnern in einer Datei. Jede Liste in einer Zeile. Aber nicht über einer maximalen Anzahl von Linien. Beim verlieren der älteste. Eine weitere mögliche Lösung wäre die Einrichtung einer windowfile. Also... Löschen Sie die erste Zeile und fügen Sie die neue Zeile am Ende. Sie wissen, wie löschen Sie die erste Zeile einer Datei?
- Sorry, Sie haben noch nicht gesagt, was das problem Sie versuchen zu lösen, ist - Sie haben dargelegt, eine mögliche (und IMHO schlechte) Lösung.
- Ist die Datei notwendig, eine text-Datei? Ist eine Festnetz-Länge machbar?
- Die Datei ist notwendig, weil es ist die Eingabe einer anderen Anwendung.
- Eine zirkuläre Datei machen würde nicht, sehr gute Eingabe für eine andere Anwendung-sicher, es ist nicht Hausaufgaben? Wenn es ist der Eingang zu einer anderen app, die Sie haben VIEL mehr Arbeit, als Sie schon gelegt hier, weil Sie kommunizieren müssen, die die aktuelle Position auf die andere app! Ich glaube nicht einmal, es ist möglich-und ich kann mir nicht vorstellen, ein Programm zu Fragen, für eine kreisförmige Datei für die Eingabe. Es muss sein, Hausaufgaben-das ist cool, so einfach sagen.
- Muss es geschrieben werden, um eine Datei sofort? Es ist eine Sache, erhalten Sie einen kreisförmigen Puffer und schreiben Sie es auf. Schreiben Sie sich eine zirkuläre Datei ist eine andere, und viel chaotischer, problem. Löschen von vorne in einer Datei ist normalerweise eine Frage der Vervielfältigung der rest der Datei. Kurz gesagt, entweder ist dies die Hausaufgaben, in diesem Fall sollten Sie das so sagen, oder ist es eine schlechte Idee, in diesem Fall sollten Sie uns sagen, was Sie zu tun versuchen, damit wir helfen können, oder es gibt einen berechtigten Grund, die wir wirklich wissen müssen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Leider kann man nicht kürzen/überschreiben von Zeilen am Anfang der Datei, ohne das umschreiben der ganzen Sache.
Neuen Vorschlag
Ich habe gerade daran gedacht, ein neuer Ansatz, der möglicherweise den trick tun für Sie...
Sie könnte einen kleinen header auf die Datei hat die folgende Struktur.
Edit: Müll, den ich gerade beschrieben habe, eine Variante der Ringpuffer!
Header-Felder
Bytes 00 - 07 (long)
- Totale (aktuelle) Anzahl der Zeilen in die Datei geschrieben.Bytes 08 - 15 (long)
- Zeiger auf den Beginn der "eigentlichen" erste Zeile in der Datei. Dieser wird zunächst das byte nach dem Kopf-Ende, aber das wird sich ändern, wenn später Daten wird überschrieben.`Bytes 16 - 23 (long)
- Länge der "end section" der Datei. Auch hier wird zunächst gleich null sein, wird aber später ändern, wenn die Daten zufällig überschrieben werden.Lese-Algorithmus (Pseudocode)
Liest die gesamte Datei.
Schreib-Algorithmus (Pseudocode)
Schreibt eine beliebige Anzahl der neuen Zeilen in die Datei.
Nicht eine furchtbar einfache algorith ich voll und ganz zugeben! Ich allerdings denke, es ist ziemlich elegante Art und Weise. Lassen Sie mich wissen, wenn einer das nicht klar, natürlich. Hoffentlich sollte es tun genau das, was Sie jetzt wollen.
Ursprünglichen Vorschlag
Nun, wenn Sie die Linien sind garantiert konstanter Länge (in bytes), Sie könnte leicht genug sucht einfach zurück auf die entsprechende Stelle und überschreiben bereits vorhandener Daten. Dies scheint wie eine ziemlich unwahrscheinliche situation jedoch. Wenn Sie nichts dagegen haben, daß die Einschränkung, dass Ihre Leitungen dürfen eine maximale Länge, und zusätzlich Polsterung jeder der Zeilen, die Sie schreiben, um diese maximale Länge, dann könnte die Sache für Sie einfach. Noch, es hat seine Nachteile, wie stark zunehmenden Größe der Datei unter bestimmten Umständen (D. H. die Linien sind viel kurzgeschlossen als die maximale Länge.) Es hängt alles von der situation, ob dies akzeptabel ist oder nicht...
Schließlich, können Sie stattdessen wollen, schauen Sie sich die Nutzung einer vorhandenen logging-system, je nach Ihren genauen Zweck.
Die übliche Weise zu behandeln, die Protokollierung, die explodieren nicht in der Größe, ist die Verwendung rolling log-Dateien, und Rollen Sie einmal einen Tag oder ähnlich, und behalten Sie nur die N neuesten Dateien.
Zum Beispiel, jeden Tag, die Sie erstellen ein neues logfile mit dem Namen `application_2009_05_20.log', und beginnen Sie zu schreiben, immer Anhängen.
Einmal haben Sie 14 Tage im Wert von logfiles, starten Sie das löschen des ältesten.
Da Dateien sind byte-orientiert, und Sie müssen eine Linie-orientierten service, haben Sie zwei Möglichkeiten:
implementieren ein line-orientierten wrapper um die Datei
wechseln einige line-orientiertes Gerät. Nur von der Spitze von meinem Kopf: SQLite hat einige nette C++ Wrapper zur Verfügung.
Verwenden Sie einen Ringpuffer und schreibt den Puffer in eine Datei für jedes add.
Hier ist eine kleine und einfache code-Größe-Lösung. Es ist eine einfache kreisförmige Puffer des strings und jedes mal, wenn Sie Zeichenfolgen, die Sie schreibt den ganzen Puffer von Zeichenfolgen in die Datei (selbstverständlich entstehen für Sie eine erhebliche Kosten für das schreiben alle die Saiten für einen einzelnen Vorgang hinzufügen. Das ist also nur geeignet für eine kleine Anzahl von strings).
Einfache Implementierung der zirkulären Puffer mit der Ausgabe in eine Datei:
Also im obigen Beispiel hatten wir 5 Zeilen der input-und unser Puffer war nur 4 Zeilen lang. Daher sollte die Ausgabe 4 Zeilen und nur die erste Zeile überschrieben werden soll, indem die Letzte Zeile "Goodbye world". Sicher genug, die erste Zeile der Ausgabe bestätigt hat, "auf Wiedersehen Welt":
Einfache Lösung:
Diese Lösung ist so konzipiert, bieten eine Konstante Länge der Datei, anstatt einer Konstanten Anzahl von Zeilen innerhalb der Datei. Die Anzahl der Zeilen wird im Laufe der Zeit variieren je nach Länge. Diese Lösung macht es schwieriger, zu versuchen, zu bestimmten Zeilennummern schnell, aber Sie bleiben einige Indikator-Daten am Anfang oder am Ende der Datei, um dies zu erleichtern.
"Clever" - Lösung (variation der Lösung oben):
Verwenden Sie einfach den gleichen trick, die manchmal verwendet für deques. Nur expicitely wrap-around-vom Anfang der Datei bis zum Ende, aber halten Sie den überblick, wo der Anfang/Ende der Datei ist. Sie schreiben, könnte ein unwrap-Dienstprogramm zum konvertieren dieser Datei in einen standard ein, wenn Sie wollte, Lesen Sie es mit einem Programm, das nicht Unterstützung es. Diese Lösung ist WIRKLICH einfach zu implementieren, aber ich mag die version oben besser.
Hässliche Lösung:
Beim hinzufügen von Linien, fügen Sie eine moderate Menge an Polsterung an jede Zeile, die Sie hinzufügen.
Jedes mal, wenn Sie wollen, eine neue Zeile hinzuzufügen, gehen Sie wie folgt vor:
Beachten Sie, dass dies funktioniert ziemlich schlecht, es sei denn, deine Zeilen sind sehr konstant über die Länge. Eine einfachere Lösung ist, um zu garantieren, Linien konstanter Länge (aber setzen Sie in irgendeiner Art und Weise erstellen multi-line "Linien" im Fall Sie überschreiten die Länge.
wenn die Dateien müssen text-Dateien:
Dies ist sehr problematisch, mit unterschiedlichen Leitungslängen. Deine ersten zwei Zeilen, 80 Zeichen, wie Sie zu überschreiben, die mit einer 100-Zeichen-Grenze?
Wenn die neue Zeile sollte ersetzen Sie die erste Zeile, würde dies im Ergebnis in einer Datei einfügen, was eine sehr teure operation ist (im Grunde genommen der ganze Rest der Datei gelesen und geschrieben werden). Sie wirklich nicht wollen, zu tun, was für alle, aber minimale Mengen von Daten.
Wenn dies für die Protokollierung Zweck verwenden rollng log-Dateien - z.B. ein Tag (wie vorgeschlagen von lassevek).
Ich machte es auch einfacher: wenn die Datei die Größe überschreitet eine Grenze, die alte Datei wird umbenannt .bak (alt .bak gelöscht) und neu zu starten. Mit einem 1-MB-Grenze, dies bewahrt z.B. die letzten 1 MB, während nie beanspruchen mehr als 2 MB.
Ihnen beschäftigen könnte einen ähnlichen Mechanismus mit zwei oder mehr Dateien. Grundsätzlich bewegen sich die "rollover", um Dateien, anstatt Linien.
wenn die Datei in einem proprietären format:
Ein Basis-DB-engine (wie SQLite, wie empfohlen), oder andere strukturierte Lagerhaltung.
Könnten Sie
log4cxx
mit einemRollingFileAppender
schreiben diese Informationen in einer log-Datei. DieRollingFileAppender
behandeln Rollen über die log-Datei, wenn es eine bestimmte Größe erreicht. Ich glaube nicht, dass es genau, was Sie wollen, aber es ist ziemlich einfach-vielleicht wird es tun.Nur eine Zuordnung erstellen der Datei in der benötigten Größe (CreateFileMapping oder mmap), schreiben die Zeilen in den Puffer und von vorne beginnen, wenn die maximale Anzahl erreicht ist.
das wird schwierig sein, da die Datei-I/O arbeitet mit bytes, wie die zugrunde liegende Einheit des Speichers, und nicht auf Zeilen.
Ich meine, man konnte nur fseek() zum Anfang zurück und verpasste die früheren Daten, aber ich habe eine Ahnung, dass ist nicht das, was Sie wollen.
Ich habe gesehen, dies geschieht durch halten der aktuellen schreiben Stellung für die Datei irgendwo. Wenn Sie brauchen, um eine Zeile hinzuzufügen, suchen Sie nach der position, schreiben der Linie, und aktualisieren Sie die position in einer atomaren Mode. Wenn Sie überlaufen, dann suchen Sie auf null, bevor Sie mit dem schreiben der Zeile. Wir tun dies auch heute für die Größe eingeschränkt kreisförmigen log-Dateien. Tun Sie es auf einer Linie-eingeschränkte basis ist ein wenig seltsam, aber konnte wahrscheinlich gemacht werden, in ähnlicher Weise. Unser schreib-Schleife sieht so aus:
Der schwierige Teil ist die Aufrechterhaltung der aktuellen schreiben Stellung und die Suche nach irgendeiner Weise zu koordinieren, die das Lesen der Datei (z.B. mit der
tail
utility) während Ihre Anwendung zu schreiben. Ihre Leser-Dienstprogramm hat zu verfolgen, die schreiben die position als gut, so dass es die lese-Schleife wird:Dieser nicht in einer bestimmten Sprache, es ist nur pseudocode, aber die Idee ist da. Natürlich verließ ich die Handhabung all die interessanten Grenzfälle für den Leser.
All das sagte... ich Stimme mit den anderen Meinungen. Tun Sie das nicht, es sei denn, Sie haben einen wirklich guten Grund. Es klingt wie eine gute Idee, aber:
grep
,tail
,perl
usw.Insgesamt, Sie werden besser mit einigen vorhandenen Paket-logging-Paket, das ermöglicht die konfigurierbare log-Datei-management. Werfen Sie einen Blick auf Apache log4cxx oder Poco ist
Poco::Logger
.Einfache Abhilfe:
Wenn Sie wollen, erstellen Sie diese Datei für die Eingabe zu einer anderen Anwendung, ich denke, Ihre beste Wette wäre, sich direkt auf eine Beziehung Datenbank (SQL Server, MySQL, was auch immer..) Dann in regelmäßigen Abständen zu generieren, die Datei bei Bedarf aus der protokollierten Daten.
Herum zu erhalten, die variable Größe ist, werden Sie wahrscheinlich am Ende mit eine Dereferenzierung und Zuweisung Schema. Diese würde darin bestehen, eine Dereferenzierung block mit einer festen Anzahl von 'Zeiger' in der Datei, und eine "weiter-zu-werden-geschrieben" - Zeiger, würde das wrap-around-N.
Aber der wichtigste trick wäre, indem die Umleitung.