# Große Dateien schnell einlesen



## Fian03 (19. Aug 2003)

Hallo

mein Programm öffnet Dateien um sie dann zu bearbeiten und zu speichern. Allerdings sind manche Dateien relativ groß (ca. 20 MB) und mein Programm braucht eine Ewigkeit um die Datei zu öffnen und sie in eine Variable zu speichern.

Ich realisiere das momentan mit einem FileReader.

Kennt jemand eine möglichkeit das einlesen zu beschleunigen? Oder kann es vielleicht sein das es am Eclipse hängt?

Hier ist der Teil um den es sich Handelt:

try 
{ 
  br = new BufferedReader(new FileReader(f)); 
  while((line = br.readLine())!= null) 
  { 
    Zaehler = Zaehler + 1;
    strFile = strFile + line; 
  }
  textArea.setLineWrap(true);
  textArea.setWrapStyleWord(true); 
  textArea.append("Datei erfolgreich geöffnet!\n");
  br.close(); 
} 
catch(FileNotFoundException fnfe) 
{ 	
  textArea.append("Datei nicht gefunden...\n" + fnfe); 
} 
catch(IOException io) 
{ 
  textArea.append("Probleme beim Lesen...\n" + io); 
} 



Vielen Dank im Vorraus

Gruß Fian03


----------



## Stefan1200 (19. Aug 2003)

Fian03 hat gesagt.:
			
		

> Kennt jemand eine möglichkeit das einlesen zu beschleunigen?
> Gruß Fian03



Meines wissens nach gibt es zwei hauptsächliche Dinge, die man extrem Beschleunigen kann, wenn man eine Datei in einen String einlesen möchte.
Zum Einen, wenn man den BufferedReader benutzt, das machst du ja schon. Zum Anderen sollte man zuerst nicht in einen String speichern!!!
Stattdessen sollte man einen StringBuffer verwenden. Nach dem Einlesen der Datei kann aber problemlos aus einem StringBuffer ein normaler String gemacht werden, falls einem nicht auch die Möglichkeiten mit dem StringBuffer reichen.

Laut deinem Source sieht es aus, als würde die Variable strFile ein normaler String sein, der immer erweitert wird. Gerade dieses Verfahren geht beim StringBuffer ein vielfaches schneller. Wenn du aus strFile ein StringBuffer machst, dann sieht deine while schleife wie folgt aus:

while((line = br.readLine())!= null) 
{ 
     Zaehler = Zaehler + 1; 
     strFile.append(line); 
}

Den Zaehler = Zaehler + 1; würde ich eventuell gegen ein Zaehler++; austauschen, bringt aber keinen oder kaum ein Geschwindigkeitszuwachs.


----------



## Nobody (19. Aug 2003)

Fian03 hat gesagt.:
			
		

> StringBuffer.indexOf



wenn du auf diesen index zugreifst und das gesuchte objekt nicht vorhanden ist, versucht er auf die stelle -1 zu zugreifen. da ich jetzt den genauen code nicht kenne, kann ich nicht sagen ob es daran liegt.


----------



## Stefan1200 (19. Aug 2003)

Fian03 hat gesagt.:
			
		

> Danke für den Tip! Ich habe es gleich ausprobiert.
> 
> Allerdings bekomme ich dann eine "java.lang.NullPointerException".
> 
> Das einzige was ich mit dem StringBuffer noch mache ist StringBuffer.indexOf und StringBuffer.substring. Ich verstehe nicht wo er auf ein Objekt zugreifen will das er nicht kennt (Das beudeutet diese Fehlermeldung doch, oder?)



Paste doch nochmal den Source (komplett) nachdem du den StringBuffer eingebaut hast. Was ist denn in der Zeile, wo der NullPointer auftritt?
Jup, NullPointer kommt dann zum Beispiel, wenn du eine Variable auslesen möchtest, in der null (nicht als String) drinn steht.

Und ich hoffe du hast nicht wirklich StringBuffer.indexOf im Source stehen, sondern strFile.indexOf und strFile.substring


----------



## Fian03 (19. Aug 2003)

Ich hatte gehofft dass ich meinen Beitrag wieder schnell genug raus genommen habe, aber trotzdem Danke für eure schnelle Hilfe. 

Ich war nur zu doof den StringBuffer richtig zu deklarieren.

  statt StringBuffer sb = new Stringbuffer;

habe ich geschrieben

  StrinBuffer sb;

das geht natürlich nicht!!!

SORRY


----------



## Stefan1200 (19. Aug 2003)

Und wie groß ist der Geschwindigkeitsunterschied mit dem StringBuffer?
Würde mich jetzt doch mal interessieren


----------



## Fian03 (19. Aug 2003)

Ich kann es dir nicht genau sagen. 

Bei einem File von 21.5 KB geht es schon merklich schneller. An mein 20 MB - File habe ich mich noch nicht ran getraut.


----------



## Stefan1200 (19. Aug 2003)

Fian03 hat gesagt.:
			
		

> Ich kann es dir nicht genau sagen.
> 
> Bei einem File von 21.5 KB geht es schon merklich schneller. An mein 20 MB - File habe ich mich noch nicht ran getraut.



Also ich habe mal ein halbwegs sinnloses Programm geschrieben, das ein selbst eingebbaren String so oft in eine Datei schreibt, wie man angegeben hat. Und wenn ich da ein Umweg einbaue, in dem ich die Textdatei vor dem schreiben in die Datei erst in einer Variable zusammen baue, gab es zwischen dem String und StringBuffer extreme unterschiede.
In diesem Beispiel ist es natürlich intelligenter gleich den String in eine Datei zu schreiben, und die Anweisung in eine Schleife zu packen, aber es war ja auch mehr ein Test, bzw. Übung.

Interessant ist auch, das die Java Version von diesem Programm schneller war, als eine RealBasic Version, obwohl der Sourcecode genauso war (abgesehen von der Java <-> Basic Syntax Unterschiede). Aber die Java Version war in der Regel eine Sekunde schneller 

Also soll mir nochmal einer Sagen, Java ist vom Prinzip her langsam 
Java ist jedenfalls schneller als Basic *g*


----------



## omosde (19. Aug 2003)

Hi,

kann dazu auch was sagen, war naemlich auch neugierig und hab das mal ausprobiert!

Als Datei die Window.java (etwa 75KB) gewaehlt und ab!

String: 35766 im Mittel
StringBuffer: 178 ms im Mittel

Das sind doch schon gravierende Unterschiede! Faktor 200! Wau!

Nicht wundern, arbeite auf nem 300 Mhz Rechner unter Debian!

Interessante Zahlen!


----------



## Fian03 (20. Aug 2003)

Stimmt, es ist wirklich gewaltig schneller. 
Ich bekomme zwar jetzt einen java.lang.OutOfMemoryError aber ich bekomme den Fehler schnell  :lol: 
Vorher bin ich gar nicht so weit gekommen


----------



## Nobody (20. Aug 2003)

dann braucht dein programm wohl etwas viel speicher, hier hilft nur speichermenge erweitern (wurde in nem anderen thread beantwortet)


----------



## marsias (1. Sep 2003)

Hi!

Wenn man string um string erweiter, wandelt java intern den string in einen stringbuffer um
erweitert den und wandelt ihn wieder in string um....das sagt doch alles eigentlich.
also leute wenn viel rumgemache mit strings dann stringbuffer nehmen   

mfg


----------



## Nobody (1. Sep 2003)

marsias hat gesagt.:
			
		

> Hi!
> 
> Wenn man string um string erweiter, wandelt java intern den string in einen stringbuffer um
> erweitert den und wandelt ihn wieder in string um....das sagt doch alles eigentlich.
> ...




bei einfachen operationen ist der stringbuffer relativ langsam, daher empfiehlt sich immer die abwägung zwischen stringbuffer und dem normalen string. im zweifelsfall hilft zeitenvergleich


----------



## aquanox (2. Sep 2003)

Hi,

schonmal überlegt das ganze Zeichenweise einzulesen? Dann übergehst du den String von readline:


```
try
{
  br = new BufferedReader(new FileReader(f));

  StringBuffer sb = new StringBuffer();
  char c;

  while(true) // Die Abfrage kommt dann später
  {
    c = br.read();
    
    if(c == '\r') // Wagenrücklauf, wird übergangen (bei readline nicht nötig)
    {
      continue;
    }
    else if((c == '\n') || (c == -1))  // Zeile ist vorbei oder Dateiende
    {
      Zaehler++; // entspricht Zaehler = Zaehler + 1

      if(c == -1)
      {
         break; // Datei ist zu Ende, jetzt wird das while verlassen
       }
    }
    else
    {
       sb.append(c);  // zeichen anhängen
    }
  }

  strFile = sb.toString();
  
  textArea.setLineWrap(true);
  textArea.setWrapStyleWord(true);
  textArea.append("Datei erfolgreich geöffnet!\n");
  br.close();
}
catch(FileNotFoundException fnfe)
{
  textArea.append("Datei nicht gefunden...\n" + fnfe);
}
catch(IOException io)
{
  textArea.append("Probleme beim Lesen...\n" + io);
}
```


----------



## Nobody (2. Sep 2003)

eine endlosschleife ist nicht serh elegant. besser wäre es c vorzubelegen und dann die abfrage ins while mit reinzunehmen


----------

