# Zeile an Anfang einer Datei einfügen



## 00d4vid (4. März 2009)

Hallo,

ich bin nun schon etwas länger am suchen und wollte hier nochmal nachfragen, ob es eine Möglichkeit gibt, am Anfang einer Datei eine Zeile einzufügen, ohne, dass der bisherige Inhalt überschrieben wird.
Möglich ist natürlich, die ganze Datei auszulesen, am Anfang einen String hinzuzufügen und dann die Datei neu zu schreiben, nur habe ich bis zu 1000 Threads die gleichzeitig schreiben und da wird das nicht allzu performant sein befürchte ich.

Gibts da in Java was?


----------



## jeipack (4. März 2009)

Hi
Die Windows API liefert das (meines Wissens) nicht - Somit Java auch nicht. Es kann also nur an eine Datei etwas angehängt werden.


----------



## vfl_freak (4. März 2009)

jeipack hat gesagt.:


> Die Windows API liefert das (meines Wissens) nicht - Somit Java auch nicht. Es kann also nur an eine Datei etwas angehängt werden.



Hallo,

das stimmt so nicht wirklich 
Es gibt die Klasse _*RandomAccessFile*_, über die man wahlfrei zugreifen kann, also auch am Anfang der Datei.
Eine ausführliche Erklärung findet ihr hier:
http://www.dpunkt.de/java/Programmieren_mit_Java/Streams/14.html

Gruß
Klaus


----------



## jeipack (4. März 2009)

Oh Danke für die Korektur 

Ich habe mich sogar noch gefragt ob ich das so schreiben soll. Das mit der Windows API habe ich mal ihrgendwo gelernt (Hoffe das ich das richtig gelernt hab/noch aktuell ist) und habs dann einfach auf Java portiert, da diese ja auch wieder auf die API zugreifft. 

Weisst du wie die RandomAccessFile intern arbeitet? 


Gruss


----------



## 00d4vid (4. März 2009)

Aber beim RandomAccessFile verändert er aber doch nicht die länge der Datei oder?
Wenn ich da in Zeile 1 eine neue Zeile einfüge dann ist die alte Zeile 1 doch gelöscht oder kann ich die einfach nach unten schieben?
Weil wenn das nicht geht müsste ich ja, um alle Daten zu behalten, wieder die Datei erst einlesen, den String anfügen und die Datei wieder schreiben oder?


----------



## hammet (4. März 2009)

> Instances of this class support both reading and writing to a random access file. A random access file behaves like a large array of bytes stored in the file system. There is a kind of cursor, or index into the implied array, called the file pointer; input operations read bytes starting at the file pointer and advance the file pointer past the bytes read. If the random access file is created in read/write mode, then output operations are also available; output operations write bytes starting at the file pointer and advance the file pointer past the bytes written. Output operations that write past the current end of the implied array cause the array to be extended. The file pointer can be read by the getFilePointer method and set by the seek method.



Hört sich für mich an, als würde intern mit einer Collection gearbeitet und die Datei so oder so eingelesen.

Also kannst du, wenn du eine Zeile nur an den Anfang setzen willst, gleich die alte Datei einlesen und eine neue erstellen (auf Basis einer temporären Datei).


----------



## vfl_freak (4. März 2009)

00d4vid hat gesagt.:


> Aber beim RandomAccessFile verändert er aber doch nicht die länge der Datei oder?
> Wenn ich da in Zeile 1 eine neue Zeile einfüge dann ist die alte Zeile 1 doch gelöscht oder kann ich die einfach nach unten schieben?



Hallo,

nein, es werden logischerweise neue Zeichen hinzugefügt!
Siehe auch das Zitat von Hamment:


> A random access file behaves like a large array of bytes stored in the file system.


So etwas wie "Zeilenweise" gibt es hier á prioiri erstmal nicht!

Lies Dir meinen Link von oben durch resp. diese Referenz:
http://www.dpunkt.de/java/Referenz/Das_Paket_java.io/63.html

Die Verwendung sollte dann etwa so laufen:

```
RandomAccessFile rafOutPut = null;
                         
int iLaenge = strRes.length();
byte[] Buffer = new byte[256];
                             
for( int k = 0; k < iLaenge; k++ )
{
    Buffer[k] = (byte)strRes.charAt( k );
}

try
{
    rafOutPut = new RandomAccessFile( "Meine_tolle_Datei.txt" , "rw" );
     rafOutPut.seek( rafOutPut.length() );
     rafOutPut.write( Buffer, 0, iLaenge);
    // void java.io.RandomAccessFile.write(byte[] b, int off, int len)
    // Writes len bytes from the specified byte array starting at offset off to this file. 
    // Parameter:
    // b the data.
    // off the start offset in the data.
    // len the number of bytes to write.
    // Löst aus:
    // IOException if an I/O error occurs.
}
```

Gruß
Klaus


----------



## deepthroat (4. März 2009)

Hi.





vfl_freak hat gesagt.:


> Hallo,
> 
> nein, es werden logischerweise neue Zeichen hinzugefügt!


Das glaube ich eher nicht. Laut der JavaDoc wird das interne "Array" nur erweitert wenn über das Ende hinausgeschrieben wird. Also logischerweise werden anderenfalls die Zeichen nur überschrieben.

Gruß


----------



## 00d4vid (4. März 2009)

Ich probiers mal aus. Danke.
Wenn das so geht wie vfl_freak geschrieben hat dann ist es super, wenn nicht dann bleibt mir wohl nix anderes übrig zu testen, ob es bei meinem Tool performant läuft wenn ich das mit Datei einlesen - String vorne anfügen - Datei neu schreiben mache.


----------



## vfl_freak (4. März 2009)

Hallo deepthroat

ich glaube, wir haben beide irgendwie Recht  

Ich finde die Stelle zwar in meinen Sourcen derzeit nicht, aber diesen Ausschnitt aus dem schönen Buch "Java ist auch eine Insel" :


> 13.2.4 Die Länge des RandomAccessFile
> 
> Mit zwei Methoden greifen wir auf die Länge der Datei zu: einmal schreibend verändernd und einmal lesend.
> 
> ...



Man muss wohl erst die aktuelle Länge auslesen und dann mit "setLength( alt + neu)" richtig setzen.

Dann sollte alles wie gewünscht funktionieren .... 

Gruß
Klaus


----------



## hammet (4. März 2009)

Ja das besagt doch aber nur, dass due die Länge der Datei ändern kannst, nicht, dass alles bei einer Änderung automatisch verschoben wird.
Das was du zitiert hast, hat deepthroat mit seiner Aussage beschrieben.


----------



## deepthroat (4. März 2009)

vfl_freak hat gesagt.:


> Man muss wohl erst die aktuelle Länge auslesen und dann mit "setLength( alt + neu)" richtig setzen.
> 
> Dann sollte alles wie gewünscht funktionieren ....


Das glaube ich erst wenn ich es sehe 

Gruß


----------



## vfl_freak (4. März 2009)

Jungs,  jetzt habt ihr mich verunsichert - und das tut mit so 'nemn alten Sack wie mir nicht 

Wie gesagt, ich finde leider die Stelle in meinem Sourcen nicht wieder, wo damit mal experimentiert hatte. Ist wohl wieder rausgeflogen - who knows why 

Es kann natürlich auch sein, dass ich mir dann zuerst noch den Rest der Datei ab Pos. X eingelesen und nach dem Schreiben (und vorherigem Längenanpassen) hinten wieder angehängt habe .....

Ach, ich werde alt - ist aber auch schon weit über ein Jahr her ....

Gruß
Klaus


----------



## hammet (4. März 2009)

vfl_freak hat gesagt.:


> Jungs,  jetzt habt ihr mich verunsichert - und das tut mit so 'nemn alten Sack wie mir nicht
> 
> Wie gesagt, ich finde leider die Stelle in meinem Sourcen nicht wieder, wo damit mal experimentiert hatte. Ist wohl wieder rausgeflogen - who knows why
> 
> ...



Das wäre möglich. Aber da ja an die erste Zeile etwas angehängt werden soll wird dann die gesamte Datei neu eingelesen und dann brauch ich auch keine RAF benutzen


----------



## vfl_freak (4. März 2009)

Ach, stimmt, er wollte immer NUR zu Beginn einfügen - das hatte ich ein wenig aus den Augen verloren  ich sach' ja - das Alter 

Ok, dann wäre der RAF in der Tat wohl eher flüssiger als flüssig .....

Wobei mich die gerade auch die anfangs erwähnten "1000 Thread, die gleichzeitig schreiben" etwas irritieren! Ich hoffe, nicht alle in die gleiche Datei, denn dann würde es wohl eh' recht finster 

Gruß
Klaus


----------



## jeipack (4. März 2009)

Oha, was hab ich hier nur ausgelöst..

Was mir noch eingefallen ist, egal wie der RAF arbeitet, bei so vielen Schreibzugriffen wird das nicht performant sein (Ausser mit einem speziell darauf ausgerichtetem FileSystem/OS).
Als Lösung vielleicht sowas:
- Eine Funktion, die alle Strings aufnimmt und nur alle paar Sekunden das File schreibt (Zur Sicherheit).
- Das File erst in umgekerter Reihenfolge schreiben und am Schluss das File einlesen und Zeile für Zeile kehren.
- Das ganze Programm so auslegen, dass es auch unten angehängt werden kann ^^


Gruss


----------



## vfl_freak (4. März 2009)

Hallo,

tja, shit happens 

So ganz genau wird Dir das ohne weitere Details  keiner sagen können!

Schreiben denn wirklich Deine 1000 Threads alle in EINE Datei ? ? ? 
Ich würde es im Zweifel wohl auch so umorganisieren, dass am Ende angehängt - das ist immer noch schneller!
Zudem ist jeder Dateizugriff teuer - also gerade das permanente Öffnen und Schliessen kostet sicher am meisten Zeit !!

Deinen zweiten Vorschlag habe ich nicht wirklich verstanden ...

Gruß
Klaus


----------



## jeipack (4. März 2009)

vfl_freak hat gesagt.:


> So ganz genau wird Dir das ohne weitere Details  keiner sagen können!


Ist nicht mein Thread / Programm, interessiert mich jetzt nur auch..



vfl_freak hat gesagt.:


> Deinen zweiten Vorschlag habe ich nicht wirklich verstanden ...


Alle Meldungen unten anhängen und wenn das 'grosse Schreiben' vorbei ist die Datei umkehren.


Gruss


----------



## 00d4vid (13. März 2009)

Nein, die schreiben nicht alle in eine Datei.
Ich erzeuge mit dem Tool Ausgaben für eine Website, d.h. ich erzeuge Html-Seiten.
Nur irgendwie hab ich noch immer keine performante Lösung für das Problem...

Gut alternativ könnte ich das ganze in meine DB schreiben und mit OrderBy die letzten Einträge ganz oben anzeigen lassen.
Nur da knallts mir dann vermutlich die DB relativ schnell voll...


----------



## Chefkoch333 (14. März 2009)

Hi,
ich denke du wirst nicht darum herum kommen die Datei neu zu schreiben. Nur musst du dazu nicht die komplette Datei im Speicher halten, sondern kannst diese einfach streamen.

Die Idee mit der DB, welche deine HTML Seite füttert halte ich persönlich am vernüftigsten.



00d4vid hat gesagt.:


> Nur da knallts mir dann vermutlich die DB relativ schnell voll...



Über welche Datenmengen sprechen wir denn? Das gleiche dürfte ja dann auch für dein Dateisystem gelten.


----------



## 00d4vid (15. März 2009)

Hmm also ich habs mal mit der Datenbank probiert, da funktioniert es bisher ganz gut


----------

