# Textzeile mitten in die Datei schreiben, ohne den Text zu ersetzen



## Andron (22. Oktober 2007)

Hallo,
meine Frage ist: wie kann ich bestehende Text-Dateien um eine Zeile erweitern?
Das Problem ist, dass die Zeile nicht an das Ende der Datei angehängt werden soll, sondern irgendwo in der Mitte. dabei dürfen die Textteile nicht überschrieben werden.
Geht das überhaupt?
Die Lösung, bei der ich die Textteile rumkopieren muss, passt leider nicht, da es manchmal bis zu 1mio Zeilen sein können.
Ich suche nach einer Lösung, bei der ich in einer Schleife schnell paar Zeilen in die Datei schreiben kann.
Hoffe, ihr könnt mir helfen.
Danke im Voraus.


----------



## Tobias Köhler (22. Oktober 2007)

Wenn es immer unterschiedliche Anzahl an Zeilen sein soll, musst du ja auch wissen wo das eingetragen werden soll... also, wie sieht die Struktur aus? Gibt es ein Signalwort oder ähnliches? Wenn, dann könntest du da vll was mit Stringbuffer, Regex oder Ähnlichem machen


----------



## waterhouse533-lp (22. Oktober 2007)

Sollen Deine neuen Zeilen an eine bestimmte Stelle oder dürfen die überall hin nur nicht an das Ende der Datei?


----------



## zerix (22. Oktober 2007)

Hallo,

du wirst die Datei ab dem Punkt wo du die Werte neu einfügst, neu schreiben müssen. Also alles neu reinschreiben müssen.

MFG

zEriX


----------



## Andron (22. Oktober 2007)

Zu Fragestellung im Allgemeinen:

In einer Applikation werden viele, sehr viele Log-Files rausgeschrieben, dabei werden DEBUG, FATAL, ERROR und WARN-Informationen in jeweils eigene Datei geschrieben.

Nun, wenn etwas schief läuft, ist es sehr schwer den genaueren Ablauf des Programms nachzuvollziehen.
Ich muss einen Parser schreiben, der die Zeilen nach dem Datum parst und diese sortiert in die Datei schreibt.
Es sind über 1 mio Zeilen und über 20 Files. Ich habe 4 verschachtelte Schleifen. Der ganze Sortiervorgang würde über 2 Tage dauern.
Ich versuche jetzt nicht nur die früheste Zeile zu ermitteln, sondern noch die späteste, somit müsste es viel schneller gehen. Meine End-Datei wächst praktisch vom Anfang und aus der Mitte.


----------



## Andron (22. Oktober 2007)

zerix hat gesagt.:


> Hallo,
> 
> du wirst die Datei ab dem Punkt wo du die Werte neu einfügst, neu schreiben müssen. Also alles neu reinschreiben müssen.
> 
> ...





Das geht leider nicht. Mir ist die Schnelligkeit sehr wichtig.
Gibt es wirklich keine Möglichkeiten?

Ich überlege gerade:
ich schreibe an einem Punkt in der Datei "\n",
dann an derselben Position meine Zeile.
Sollte doch funktionieren, oder?


----------



## zerix (22. Oktober 2007)

Du darfst das nicht so sehen wie im Texteditor. Wenn du an eine Stelle was schreibst, dann wird das was vorher da war ersetzt und nicht weitergeschoben.
Also wird es nicht so funktioniere. 

Dann wirst du dir, meiner Meinung nach zumindest, was einfallen lassen müssen, die Datei von Anfang bis zum Ende zu schreiben.


Da fällt mir aber ein. Log-Dateien sind doch nach Datum sortiert. 

MFG

zEriX


----------



## Andron (22. Oktober 2007)

zerix hat gesagt.:


> Du darfst das nicht so sehen wie im Texteditor. Wenn du an eine Stelle was schreibst, dann wird das was vorher da war ersetzt und nicht weitergeschoben.
> Also wird es nicht so funktioniere.
> 
> Dann wirst du dir, meiner Meinung nach zumindest, was einfallen lassen müssen, die Datei von Anfang bis zum Ende zu schreiben.
> ...




.Log-Dateien sind nicht nach dem datum sortiert, und wenn, dann nur innerhalb einer Datei. Ich habe mehrere, je eine für WARN, DEBUG, FATAL und ERROR. Ich muss die alle in eine überführen. Außerdem habe ich fast 20 Warn's, 3 Errors's und 2 Fatal's. Die DEBUG-Dateien wollen wir jetzt nicht parsen, weil die alle (über 20 Stück) je 64k Zeilen enthalten. Damit würde das Ganze fast 2 Wochen dauern.


----------



## zerix (22. Oktober 2007)

Also alle Logger die ich kenne, schreiben jedes Ereignis nacheinander. Damit ist alles sortiert. Ich meine ja auch in einer Datei. 

Damit hast du dann doch gar kein Problem. Du kannst doch jede Datei öffnen und immer von der Datei lesen die du brauchst. 

Ich versuche mal an einem Beispiel zu erklären wie du es machen könntest. 

Du hast 3 Dateien. Von allen 3 Dateien liest du einen Log-Eintrag aus. Du schaust welcher der frühere ist und schreibst diesen in die Zieldatei. Angenommen der von Datei 1 war der frühere. Dann wird der in die Datei geschrieben. Dann liest du wieder einen Log-Eintrag aus Datei 1. Dann wird wieder geschaut welcher ist der frühere. So geht das dann weiter bis alle Dateien am Ende sind. 

So baust du die Datei von Anfang an auf. Ich kann mir nicht vorstellen, dass das so langsam sein soll. Also so langsam dass es mehrere Tage braucht.

MFG

zEriX


----------



## Andron (22. Oktober 2007)

zerix hat gesagt.:


> Also alle Logger die ich kenne, schreiben jedes Ereignis nacheinander. Damit ist alles sortiert. Ich meine ja auch in einer Datei.
> 
> Damit hast du dann doch gar kein Problem. Du kannst doch jede Datei öffnen und immer von der Datei lesen die du brauchst.
> 
> ...





Genau so mache ich.
Eine Zeile wird mit allen Zeilen einer Datei in ca. 1sek vergliechen.
Ich habe über 1 mio Zeilen.
Das sind schon mal über 200 Stunden .

Im Moment mache ich das so, dass die weggeschriebene Zeile aus der Quelldatei gelöscht wird. Klappt alles wunderbar. Speicherverbrauch liegt bei etwa 8MB, CPU ist zu 90% ausgelastet, alles läuft.
Mir ist auch klar, dass es zu Ende schneller gehen wird. Es wird aber erwartet, dass das Programm innnerhalb von max. 1-3 Stunden alles erledigt.


----------



## MiMi (22. Oktober 2007)

Aber du musst doch net eine Zeile mit ALLEN Zeilen vergleichen? Du musst doch immer nur 3 Zeilen vergleichen


----------



## Andron (22. Oktober 2007)

mimij85 hat gesagt.:


> Aber du musst doch net eine Zeile mit ALLEN Zeilen vergleichen? Du musst doch immer nur 3 Zeilen vergleichen




Hier ein Auszug aus einer der Warn-Dateien:

```
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,607 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,608 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.dal.connection.impl.mdg.MDGConnection 2007-10-17 18:49:25,550 -- WARN -- [getArrayResultSet] received invalid MDG object for query: prices/status?VERSION=2&ID_QUALITY_PRICE=4&LANG=it&CODE_QUALITY_PRICE=BST&ZID=363234383035333b31303138303b753913b12850483b18899676963b&G_ID_USER_SESSION=6248053 / Error:MdgError (10000)(10000):10000:need ID_NOTATION or ID_INSTRUMENT
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,608 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,609 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,609 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,611 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.dal.connection.impl.mdg.MDGConnection 2007-10-17 18:49:25,541 -- WARN -- [getArrayResultSet] received invalid MDG object for query: prices/status?VERSION=2&ID_QUALITY_PRICE=4&LANG=it&CODE_QUALITY_PRICE=BST&ZID=363234383035333b31303138303b753913b12850483b18899676963b&G_ID_USER_SESSION=6248053 / Error:MdgError (10000)(10000):10000:need ID_NOTATION or ID_INSTRUMENT
com.idms.dal.connection.impl.mdg.MDGConnection 2007-10-17 18:49:25,612 -- WARN -- [getArrayResultSet] received invalid MDG object for query: prices/status?VERSION=2&ID_QUALITY_PRICE=4&LANG=it&CODE_QUALITY_PRICE=BST&ZID=363234383035333b31303138303b753913b12850483b18899676963b&G_ID_USER_SESSION=6248053 / Error:MdgError (10000)(10000):10000:need ID_NOTATION or ID_INSTRUMENT
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,612 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,612 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,613 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,613 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,615 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,616 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
com.idms.web.core.struts.tiles.IDMSFactorySet 2007-10-17 18:49:25,617 -- WARN -- [getDefinitionsFactoryKey] no definition found! Returning null! This will result in loading the default-definition wich is the root-defintion!
```

Wie man sieht, sind die Ausgaben nicht sortiert. Ich muss alle Dateien durchlaufen und mit allen Zeilen vergleichen.


----------



## zerix (22. Oktober 2007)

Jede Log-Datei muss nach dem Datum sortiert sein. Also brauchst du nicht, eine Zeile mit allen einer Datei zu vergleichen. 
Les von jeder Datei eine Zeile. Suchst du von diesen 3 Zeilen, die Zeile raus die früher geschrieben wurde. Schreibst diese Zeile, dann in die neue Datei. Damit hast du diese eine Zeile nur mit den beiden anderen verglichen. Angenommen diese Zeile war aus Datei eins. Dort steht der Reader jetzt am Anfang der zweiten Zeile. Diese liest du dann ein. Die anderen zwei Zeilen aus den anderen Dateien müssen ja immer noch gespeichert sein. Also hast du wieder 3 Zeilen die du mit einander vergleichen musst. 
Davon schreibst du dann wieder  die frühere in die Zieldatei. Angenommen, diese war von Datei 3. Dann liest du die nächste Zeile von Datei 3 ein.
Dann hast du ja wieder insgesamt 3 Zeilen die du miteinander vergleichen musst. Das ganze geht dann soweiter. 

So musst du jede Zeile maximal mit 2 anderen Zeilen vergleichen und nicht mit einer Million. Du musst auch nichts löschen. So hast du wenn du alle 3 Dateien einmal eingelesen hast, die Zieldatei fertig.

MFG

zEriX


----------



## MiMi (22. Oktober 2007)

Naja da die alle von "2007-10-17 18:49:25" sind, is da net viel zu vergleichen ^^


----------



## Andron (22. Oktober 2007)

zerix hat gesagt.:


> Jede Log-Datei muss nach dem Datum sortiert sein. Also brauchst du nicht, eine Zeile mit allen einer Datei zu vergleichen.
> Les von jeder Datei eine Zeile. Suchst du von diesen 3 Zeilen, die Zeile raus die früher geschrieben wurde. Schreibst diese Zeile, dann in die neue Datei. Damit hast du diese eine Zeile nur mit den beiden anderen verglichen. Angenommen diese Zeile war aus Datei eins. Dort steht der Reader jetzt am Anfang der zweiten Zeile. Diese liest du dann ein. Die anderen zwei Zeilen aus den anderen Dateien müssen ja immer noch gespeichert sein. Also hast du wieder 3 Zeilen die du mit einander vergleichen musst.
> Davon schreibst du dann wieder  die frühere in die Zieldatei. Angenommen, diese war von Datei 3. Dann liest du die nächste Zeile von Datei 3 ein.
> Dann hast du ja wieder insgesamt 3 Zeilen die du miteinander vergleichen musst. Das ganze geht dann soweiter.
> ...



Das ist richtig, jedoch entstehen durch Threads solche Differenzen, sehe Auszug oben.
Habe jetzt geschaut, alle Dateien sind nach dem Datum sortiert, wie du es auch sagtest, an manchen Stellen jedoch sieht man Unregelmäßigkeiten.


----------



## Andron (22. Oktober 2007)

mimij85 hat gesagt.:


> Naja da die alle von "2007-10-17 18:49:25" sind, is da net viel zu vergleichen ^^




schön wäre's .


----------



## Arnulf1 (22. Oktober 2007)

Du mußt die Datei in den Buffer zunächst einlesen. Die eigentliche Veränderung durch Hinzufüger einer Zeile sieht dann etwas so aus:

 BufferedReader reader = new BufferedReader(
       new InputStreamReader( method.getResponseBodyAsStream()));
   StringBuffer buffer = new StringBuffer();
   String line = null;
   while( ( line = reader.readLine()) != null) {
     buffer.append( line );
     buffer.append( "\n" );
   }
-------------------------------------------------------------------------
Etwas deutlicher wird es auf der Seite:

http://www.javatip.de/applet_io.html

(Zugreifen auf Dateien;Zurückschreiben von Dateien)

--------------------------------------------------------------------------
import java.io.*;
import java.net.*;
import java.applet.*;

public class MyApplet extends Applet
{
  // some other code of the Applet

  protected String writeData(String filename, String data)
  {
    StringBuffer result = new StringBuffer();
    try
    {
      // create new URL and open a connection
      URL url = new URL (getCodeBase(), filename);
      UrlConncetion con = url.getConnection();
      // set connection attributes to handle output and input
      con.setDoOutput(true);
      con.setDoInput(true);
      con.setAllowUserInteraction(false);
      // get the OutputStream and writes the data into
      OutputStream os = con.getOutputStream();
      os.write(data.getBytes());
      os.close();
      // get the InputStream and read the response
      InputStream is = con.getInputStream();
      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      String line = reader.readLine();
      while (line != null)
      {
        result.append(line);
        line = reader.readLine();
      }
      reader.close();
    }
    catch (MalformedURLException ex) {ex.printStackTrace();}
    catch (IOException ex) {ex.printStackTrace();}
    return result.toString();
  }

    // some other code of the Applet
}

----------------------------------------------------------------------
Du mußt die Zeile zunächst finden....if line.contains("etwas")
und dann ....neue Zeile = reader.readLine();
-----------------------------------------------------------------------
Weitere Beispiele zur Schreibweise findest Du auch unter:

http://www.javakb.com/Uwe/Misc/SR.aspx?p=buffer(append.line


Arnulf


----------



## Andron (23. Oktober 2007)

Wie ich in eine Datei eine Textzeile einfüge, weiß ich.
Das Problem ist, dess die Enddatei über 1mio Zeilen groß sein kann und das Hinzufügen sehr schnell erfolgen muss.
Ich denke, für dieses Problem gibt es keine Lösung, zumindest noch nicht.
Muss mir was anderes einfallen lassen.
Danke für Eure Bemühungen.


----------

