# Datei einlesen, bearbeiten, ausgeben



## Noar (30. Mrz 2009)

Hi ich möchte eine Datei einlesen, mehrfach bearbeiten und anschließend in ein neues File schreiben.

Die Datei wird dreischrittig bearbeitet. Dabei ist es für den jeweis folgenden Schritt notwendig, den vorhergehenden komplett zu durchlaufen.

Momentan gehe ich so vor:
Ich lese die Datei jeweils zeilenweise ein, bearbeite sie, schreibe sie in ein neues File.
Anschließend wird sie im nächsten Schritt wieder neu eingelesen.
Dies temporären Zwischenschritte (Files) werden am Ende wieder gelöscht.

Prinzipiell ist das ja ok, allerdings wüsste ich gern, ob ich eine Datei auch einfach in den Speicher einlesen kann und anschließend von dort Zeilenweise mehrfach bearbeiten kann.

Ich würde gern nur das Endergebnis rausschreiben.

Jemand ne Idee?

Gruß
Noar


----------



## hdi (31. Mrz 2009)

Naja du kannst mit einem StringBuilder arbeiten. D.h. du liest die komplette Datei
in einen StringBuilder ein.
Du musst dir halt dann ein paar Dinge per Hand schreiben, zB kannst du auf sowas
kein readLine() o.ä. machen, sondern bräuchtest eine eigene Methode,
die dir die "\n" in dem StringBuilder prüft, um so zu wissen was eine Zeile ist.

Ist halt mehr Arbiet, aber dann kannst du alle 3 Schritte nacheinander auf diesem
Builder machen, und erst wenn alles fertig ist schreibst du den Inhalt davon
in ein File auf die Platte.

Ist nur das, was mir spontan einfällt. Heisst nicht, dass es nicht eine viel bessere 
Methode dafür gibt, zB wirklich ein File in den Heap schreiben oder sowas.


----------



## Spacerat (31. Mrz 2009)

Ja, man kann die Dateien im Speicher halten. Entweder alles in einem wie hdi sagt oder Zeilenweise mit einem String-Array[highlight=java]void fileWorker(String fileName)
throws IOException {
  String[] lines = readFile(new FileReader(fileName));
  // Bearbeiten 1
  for(String line : lines) {
  }
  // Bearbeiten 2
  for(String line : lines) {
  }
  // Bearbeiten 3
  for(String line : lines) {
  }
  writeFile(new FileWriter(fileName), lines);
}

String[] readFile(Reader r)
throws IOException {
  ArrayList<String> lines = new ArrayList<String>();
  BufferedReader br = new BufferedReader(r);
  String line;
  while((line = br.readLine()) != null) lines.add(line);
  br.close();
  r.close(); //bin mir nicht sicher, könnte überflüssig sein.
  return lines.toArray(new String[lines.length]);
}

void writeFile(Writer w, String[] lines)
throws IOException {
  PrintWriter pw = new PrintWriter(w);
  for(String line : lines) {
    pw.println(line);
  }
  pw.close();
  w.close(); // s.o.
}[/highlight]
@Edit: Wenn ich es mir recht überleg', kann man sogar mit der ArrayList<String> arbeiten. dann kann man nämlich ganz bequem auch ganze Zeilen löschen, vertauchen usw.


----------



## mvitz (31. Mrz 2009)

Mal eine Frage dazu (könnte leicht OT) sein.

Es ist ja auch per Scanner möglich Dateien einzulesen, und dann per scanner.nextLine() auszugeben/bearbeiten etc.

Was ist hier der zu bevorzugende Weg? Gibt es dazu evtl. einfach die "best practice" das per BufferedReader zu machen oder ist er einfach schneller oder, oder, oder?


----------



## Spacerat (31. Mrz 2009)

Rein theoretisch sollte alles was "Buffered" ist besser sein als alles was "Cached" ist. <noch mehr offtopic>Lange bevor es "Scanner" gab, habe ich angefangen, mir einen erweiterten "StreamTokenizer" zu entwickeln dem man ausschliesslich "BufferedReader" bzw. "BufferedInputStream" übergeben kann.</noch mehr offtopic>"Scanner" hab' ich deswegen noch nicht verwendet, weil ich mir einfach nicht vorstellen kann, das der Zugriff auf gecachte Objekte, die ja immerhin auch mehr Speicher anfordern, weil sie per "new" instanziert werden, schneller stattfinden kann, als das man mit "mark" und "reset" von "Buffered" den Stream einfach erneut liest.


----------



## Noar (31. Mrz 2009)

Hi,

danke für die Hilfe.
Der Tip mit dem ArrayList ist super.

Werde das jetzt mal ausprobieren und schauen, wie es mit der Performance (speziell bei großen Dateien) aussieht.

Gruß
Noar


----------

