Advanced   Java   Services Lesen und Schreiben von Textdateien Back Next Up Home


Öffnen einer TextDatei zum Lesen

Wir verwenden die Klasse FileReader. Will man einen gepufferten Zugriff, so verwendet man stattdessen die Klasse BufferedReader, die ihrerseits auf die Klasse Reader aufsetzt. FileReader und BufferedReader sind reale Ableitungen der abstrakten Basisklasse Reader (siehe Hierarchie der Readerklassen ).

Wir verwenden die Klasse FileReader. Will man einen gepufferten Zugriff, so verwendet man stattdessen die Klasse BufferedReader, die ihrerseits auf die Klasse Reader aufsetzt. FileReader und BufferedReader sind reale Ableitungen der abstrakten Basisklasse Reader (siehe Hierarchie der Readerklassen ).

Wichtige Konstruktorender Klasse FileReader
FileReader(String fileName)
 
Creates a new FileReader, given the File to read from.
FileReader(File file)
 
Creates a new FileReader, given the File to read from.
Wichtige Konstruktoren der Klasse BufferedReader
BufferedReader(Reader in)
 
Create a buffering character-input stream that uses a default-sized input buffer.
Man muß schon den Quellcode lesen, um herauszufinden, wie groß "default-sized" ist. Dort finden man den folgenden Eintrag:
private static int defaultCharBufferSize = 8192;
BufferedReader(Reader in, int sz)
 
Create a buffering character-input stream that uses an input buffer of the specified size.




Lesen einer TextDatei

Reader stellt drei Lesemethoden zum Einlesen von Textdaten aus Dateien bereit.

Lesemethoden der Klasse Reader
Returntyp Name der Methode
int
 
 
 
read()

Read a single character. Returns the character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached.
int
 
 
read(char[] cbuf)
Read characters into an array. Returns the number of characters read, or -1 if the end of the stream has been reached.
abstract int
 
 
read(char[] cbuf, int off, int len)
Read characters into a portion of an array. Returns the number of characters read, or -1 if the end of the stream has been reached. Parameters: cbuf - Destination buffer, off - Offset at which to start storing characters, len - Maximum number of characters to read.

Die ersten beiden read-Methoden stützen sich dabei auf die dritte abstrakte Methode, wie ein Blick in den Quellcode zeigt.

Quellcode der ersten read-Methode:

public int read() throws IOException
{
   char cb[] = new char[1];
   if (read(cb, 0, 1) == -1)
      return -1;
   else
      return cb[0];
}

Quellcode der zweiten read-Methode:

public int read(char cbuf[]) throws IOException
{
   return read(cbuf, 0, cbuf.length);
}

Damit ist auch klar, wie die zweite Methode arbeitet, sie liest höchstens so viele Zeichen ein, wie in dem Array Platz haben. Die folgenden Beispiele demonstrieren die drei Methoden.


Zeichen für Zeichen einlesen mit int read()
FileReader fr = null;

try
{
   String fileName="TextDateiLesen.java";
   fr = new FileReader(fileName);
   StringBuffer sb = new StringBuffer();
   int ch;
   while( (ch=fr.read()) != -1 )
      sb.append((char)ch);

   System.out.println(sb.toString());
}
/*catch(FileNotFoundException ex)
{
   System.out.println(ex);
}*/
catch(IOException ex)
{
   System.out.println(ex);
}
finally
{
   try
   {
     if(fr!=null) fr.close();
   }
   catch(Exception ex)
   {
   }
}

Datei auf einmal lesen mit int read(char[] cbuf)
FileReader fr = null;

try
{
   String text ;
   String fileName="TextDateiLesen2.java";
   File file = new File(fileName) ;
   int len = (int)file.length() ;
   char[] buf = new char[len] ;

   fr = new FileReader(file);
   fr.read(buf) ;
   text = new String(buf);
   System.out.println(text);
}
/*catch(FileNotFoundException ex)
{
   System.out.println(ex);
}*/
catch(IOException ex)
{
   System.out.println(ex);
}
finally
{
   try
   {
     if(fr!=null) fr.close();
   }
   catch(Exception ex)
   {
   }
}

Datei auf einmal lesen mit int read(char[] cbuf, int offset, int length)
FileReader fr = null;

try
{
   String text ;
   String fileName="TextDateiLesen2.java";
   File file = new File(fileName) ;
   int len = (int)file.length() ;
   char[] buf = new char[len] ;

   fr = new FileReader(file);
   fr.read(buf, 0, len) ;
   text = new String(buf);
   System.out.println(text);
}
/*catch(FileNotFoundException ex)
{
   System.out.println(ex);
}*/
catch(IOException ex)
{
   System.out.println(ex);
}
finally
{
   try
   {
     if(fr!=null) fr.close();
   }
   catch(Exception ex)
   {
   }
}

Die Klasse BufferedReader stellt eine weitere Einlesemethode zur Verfügung, die ein zeilenweises Einlesen einer Textdatei ermöglicht.

Zusätzliche Lesemethode der Klasse BufferedReader
Returntyp Name der Methode
String
 
 
 
readLine()

Read a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed. Returns a String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached.


Datei zeilenweise und gepuffert einlesen mit String readLine() aus BufferdReader
FileReader fr = null;
BufferedReader br = null;

try
{
   String fileName="TextDateiLesen3.java";
   File file = new File(fileName) ;
   fr = new FileReader(file);
   br = new BufferedReader(fr) ;

   String line ;
   StringBuffer sb = new StringBuffer();
   // systemeigenes Zeilenumbruchszeichen ermitteln
   String sep = System.getProperty("line.separator");

   while( (line=br.readLine()) != null )
      sb.append(line+sep) ;

   System.out.println(sb);  //ganze Datei ausgegeben
}
/*catch(FileNotFoundException ex)
{
   System.out.println(ex);
}*/
catch(IOException ex)
{
   System.out.println(ex);
}
finally
{
   try
   {
     if(br!=null) br.close();
     if(fr!=null) fr.close();
   }
   catch(Exception ex)
   {
   }
}

readLine() verhält sich neutral und liest keinen Zeilenumbruch mit ein. So kann man selbst bestimmen, welches Zeilenumbruchszeichen man verwendet. Im obigen Fall wird das systemeigene Zeilenumbruchszeichen verwendet, welches man sich über die SystemProperties besorgt.


Systemabhängige Zeilenumbrüche

Seit der Zeit der Telegraphie, in der der ASCII-Code eingeführt wurde, werden die Zeichen

CR = carriage return = ASCII-Code 13 = '\r'

und

LF = line feed = ASCII-Code 10 = '\n'

zur Zeilentrennung verwendet. Als der ASCII-Code zur Speicherung von Texten in Dateien übernommen wurde, konnte man sich nicht auf ein einheitliches Zeilenumbruchszeichen verständigen. So gibt es nun drei verschiedene Zeilenumbruchszeichen:

Max-Systeme verwenden CR = carriage return = ASCII-Code 13 = '\r'

Unix-Systeme verwenden LF = line feed = ASCII-Code 10 = '\n'

Windows-Systeme verwenden CR+LF = carriage return+line feed = "\r\n"

Beim Einlesen mit den read()-Methoden werden sämtliche Zeichen gelesen, also auch die Zeilenumbruchszeichen. Nicht alle Varianten können können von den graphischen Komponenten in Java umgesetzt werden.

java.awt.TextArea
Methode Verhalten
setText() Mac-Zeilenumbrüche werden als schwarze Recktecke dargestellt. Es wird kein Zeilenumbruch gemacht. Unix-Zeilenumbrüche und Windows-Zeilenumbrüche werden korrekt dargestellt.
getText() In die TextArea eingegebene Zeilenumbrüche werden als Unix-Zeilenumbrüche in den Text aufgenommen. Es kann also im Text einer TextArea u.U. verschiedene Zeilenumbruchstile geben.

javax.swing.JTextArea
Methode Verhalten
setText() Mac-Zeilenumbrüche werden nicht dargestellt. Es wird kein Zeilenumbruch gemacht. Der Text läuft nathlos weiter.
Unix-Zeilenumbrüche und Windows-Zeilenumbrüche werden korrekt dargestellt.
getText() In die JTextArea eingegebene Zeilenumbrüche werden als Unix-Zeilenumbrüche in den Text aufgenommen. Es kann also im Text einer JTextArea u.U. verschiedene Zeilenumbruchstile geben.


Vermeiden systemabhängiger Zeilenumbrüche

Die Klasse System liefert das (systemabhängige) Zeilenumbruchszeichen über die Properties der Klasse System.

String separator = System.getProperty("line.separator") ;

Die Klasse Character besitzt eine Konstante

Character.LINE_SEPARATOR

Diese Konstante steht für CR, also für das Zeilenumbruchszeichen auf Mac.


Einen Text mit einheitlichen Zeilenumbruchszeichen versehen

Mit einem StringReader kann man Strings so behandeln wie Dateien. Steckt man ihn in einen BufferedReader, so steht die readLine()-Methode zur Verfügung und man kann den String zeilenumbruchsneutral einlesen. Das folgende Beispiel liest einen String mit unterschiedlichen Zeilenumbruchszeichen und gibt einen neuen String mit Unix-Zeilenumbruchszeichen zurück:

public String insertUnixLineWrappings(String text)
{
   BufferedReader br = null;

   try
   {
      //"Datei öffnen"
      br = new BufferedReader( new StringReader(text) );
      StringBuffer sb = new StringBuffer();

      String line; // "Datei" lesen
      while (  (line=br.readLine() )!=null )
         sb.append(line + '\n');

      return sb.toString();
   }
   catch(IOException ex)
   {
      return null;
   }
   finally
   {
      try
      {
         if(br!=null) br.close();
      }
      catch(Exception ex)
      {
      }
   }
}

Natürlich kann man die Methode noch flexibler gestalten, indem man als zweiten Parameter das einzufügende Zeilenumbruchszeichen eingibt:

public String insertLineWrappings(String text, String style)
{
   if ( style.equals("\r") || style.equals("\n") || style.equals("\r\n")
   {
      BufferedReader br = null;

      try
      {
         //"Datei öffnen"
         BufferedReader br = new BufferedReader( new StringReader(text) );
         StringBuffer sb = new StringBuffer();

         String line; // "Datei" lesen
         while (  (line=br.readLine() )!=null )
            sb.append(line + style);

         // Datei schließen
         br.close();
         return sb.toString();
      }
      catch(IOException ex)
      {
         return null;
      }
      finally
      {
         try
         {
            if(br!=null) br.close();
         }
         catch(Exception ex)
         {
         }
      }
   }
   else
      throw new IllegalArgumentException("second paramater contains no wrap style");
}

Anmerkung zu return in try, catch, finally

Die beiden letzten Beispiele werfen die Frage auf, in welcher Reihenfolge try, catch und finally abgearbeitet werden, wenn in den Blöcken return auftritt. Die Antwort: Der finally-Block wird in jedem Fall ausgeführt und er wird zudem vor return abgearbeitet!


Öffnen einer TextDatei zum Schreiben

Zum Schreiben von Dateien braucht man die Klasse FileWriter. Will man einen gepufferten Zugriff, so verwendet man zusätzlich die Klasse BufferedWriter. Beide Klassen sind reale Ableitungen der abstrakten Basisklasse Writer, die das Gegenstück zur Klasse Reader ist (siehe Hierarchie der Writerklassen ).

Wichtige Konstruktorender Klasse FileWriter
FileWriter(String fileName)
 
Constructs a FileWriter object given a file name.
FileWriter(String fileName, boolean append)
 
Constructs a FileWriter object given a file name with a boolean indicating whether or not to append the data written.
FileWriter(File file)
 
Constructs a FileWriter object given a file object.
FileWriter(File file, boolean append) Constructs a FileWriter object given a file object with a boolean indicating whether or not to append the data written.
Die Konstruktoren der Klasse BufferedWriter
BufferedWriter(Writer out)
 
Create a buffering character-output stream that uses a default-sized input buffer.
Man muß schon den Quellcode lesen, um herauszufinden, wie groß "default-sized" ist. Dort finden man den folgenden Eintrag:
private static int defaultCharBufferSize = 8192;
BufferedWriter(Writer out, int sz)
 
Create a buffering character-output stream that uses an input buffer of the specified size.


Schreiben einer TextDatei

Writer stellt gleich fünf Methoden zum Schreiben von Textdaten in Dateien bereit.

Schreibmethoden der Klasse Writer
Returntyp Name der Methode
void write(char[] cbuf)
Write an array of characters.
abstract void write(char[] cbuf, int off, int len)
Write a portion of an array of characters. Parameters: cbuf - Array of characters, off - Offset from which to start writing characters, len - Number of characters to write.
void write(int c)
Write a single character. The character to be written is contained in the 16 low-order bits of the given integer value; the 16 high-order bits are ignored.
void write(String str)
Write a string
void write(String str, int off, int len)
Write a portion of a string. Parameters: str - a String, off - offset from which to start writing characters, len - number of characters to write
Weitere wichtige Methoden der Klasse Writer
Returntyp Name der Methode
Writer append(char c)
Appends the specified character to this writer (Since 1.5).
Writer append(CharSequence csq)
Appends the specified character sequence to this writer (Since 1.5).
abstract void flush()
Flush the stream.

Die realen write-Methoden stützen sich letzten Endes alle auf die abstrakte write-Methode. Hier nur der Quellcode von zwei der vier Methoden.

public void write(char cbuf[]) throws IOException
{
   write(cbuf, 0, cbuf.length);  // abstrakt
}
public void write(String str) throws IOException
{
   write(str, 0, str.length());
   // diese Methode verwendet dann die abstrakte write-Methode.
}


Speichern mit dem FileWriter
FileWriter fw = null;

try
{
   fw = new FileWriter("datei.name");
   fw.write(text);  // text ist ein String
}
catch(IOException ex)
{
   System.out.println(ex);
}
finally
{
   if (fw != null)
      try
      {
        fw.close();
      }
      catch(Exception ex)
      {
      }
}

Zum Schreiben eines betriebssystemabhängigen Zeilenumbruchs bietet BufferedWriter die Methode newLine() an.

Nützliche Methode der Klasse BufferedWriter
Returntyp Name der Methode
void newLine()
Write a line separator. The line separator string is defined by the system property line.separator, and is not necessarily a single newline ('\n') character: String separator = System.getProperty("line.separator").


Speichern mit dem BufferedWriter
BufferedWriter bw = null;

try
{
   bw = new BufferedWriter( new FileWriter("datei.name") );
   bw.write(text);  // text ist ein String
   // bw.newLine() ;    // evtl. Zeilenumbruchszeichen einfügen
}
catch(IOException ex)
{
   System.out.println(ex);
}
finally
{
   if (bw != null)
      try
      {
        bw.close();
      }
      catch(Exception ex)
      {
      }
}
Valid XHTML 1.0 Strict top Back Next Up Home