File-IO in Java

Auf die Unterscheidung bei der Untersuchung von Dateiinhalten wurde bereits im Kapitel Charset Handling hingewiesen. Hier soll jetzt anhand von einigen Beispielen dargestellt werden, welche Möglichkeiten es überhaupt gibt, innerhalb des lokalen Dateisystems auf Dateien zugreifen zu können.

Zunächst einmal soll dargestellt werden, wie das Dateisystem nach dem Vorhandensein bestimmter Dateitypen durchsucht werden kann. Dazu wird eine zentrale Methode (scanDir(File dir) in unserem Beispiel) implementiert, die sich so lange rekursiv aufruft, bis der komplette Ast untersucht wurde. Mit Hilfe einer weiteren Methode (isWantedFile(File file)) werden dabei die Dateien herausgefiltert, die einer weiteren Bearbeitung zugeführt werden sollen.

import java.io.*;

public class FilesExample1 
{ public static void main(String[] args)
  { scanDir(new File("C:/"));
  }

  static void scanDir(File dir)
  { if (dir.exists() && dir.canRead() && dir.isDirectory())
    { File[] files = dir.listFiles();
      if (files != null)
      { for (File file: files)
        { if (file.isDirectory()) 
          { scanDir(file);
          }
          else
          { if (isWantedFile(file)) // gesonderte Behandlung ...
            { System.out.println(file.getPath());
            }
          }
        }
      }
    }
  }
  
  static boolean isWantedFile(File file)
  { String[] mimeTypes = { ".bmp", ".gif", ".jpg", ".png", ".tif" };
    String fileName = file.getName().toLowerCase();
    for (String mimeType: mimeTypes)
    { if (fileName.endsWith(mimeType)) return true;
    }
    return false;
  }
}

Dateien aus einer .zip Datei extrahieren

Während ein Verzeichnis im normalen Dateisystem hierarchisch angeordnet ist, besteht ein .zip Verzeichnis aus einer Anzahl von einzelnen Einträgen, die sequentiell durchsucht werden können. Ausgehend von der Hilfsklasse java.util.zip.ZipFile stellt diese eine Enumeration von java.util.zip.ZipEntry Objekten zur weiteren Verarbeitung zur Verfügung:

import java.util.*;
import java.util.zip.*;

public class FilesExample2 
{ public static void main(String[] args) throws Exception
  { ZipFile zipFile = new ZipFile("C:/Archiv.zip");
    Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
    while(zipEntries.hasMoreElements())
    { ZipEntry zipEntry = zipEntries.nextElement();
      if (isWantedEntry(zipEntry))
      { System.out.println(zipEntry.getName());
        // lesen des Inhaltes via 
        // InputStream is = zipFile.getInputStream(zipEntry);
      }
    }
  }

  static boolean isWantedEntry(ZipEntry zipEntry)
  { if (!zipEntry.isDirectory())
    { String[] mimeTypes = { ".bmp", ".gif", ".jpg", ".png", ".tif" };
      String lowerCaseName = zipEntry.getName().toLowerCase();
      for (String mimeType: mimeTypes)
      { if (lowerCaseName.endsWith(mimeType)) return true;
      }
    }
    return false;
  }
}

Verzeichnis in eine .zip Datei packen

Das folgende Beispiel implementiert eine Routine, bei der ein komplettes Verzeichnis in eine .zip Datei komprimiert wird. Folgende Randbedingungen sind zu beachten und erfordern ggf. eine Anpassung, falls andere Ausgangsbedingungen bestehen:

  1. Das zu komprimierende Verzeichnis muss als kompletter Pfad angegeben werden, wobei als Pfad-Separator "/" zu verwenden ist.
  2. Der Pfadname des zu komprimierenden Verzeichnisses darf NICHT mit "/" terminiert werden.
  3. Die .zip Datei wird in dasselbe Verzeichnis abgelegt, in der sich das zu komprimierende Verzeichnis befindet.
  4. Die komprimierte Ergebnisdatei hat den gleichen Dateinamen wie das zu komprimierende Verzeichnis plus einer .zip Endung (im folgenden Beispiel: "C:/temp/TestArchiv.zip").
import java.io.*;
import java.util.zip.*;

public class DirectoryZipper 
{ int prefixLength;
  ZipOutputStream zipOut;
  byte[] ioBuffer = new byte[4096];

  public DirectoryZipper(String dirFileName) throws Exception
  { prefixLength = dirFileName.lastIndexOf("/") + 1;
    zipOut = new ZipOutputStream(new FileOutputStream(dirFileName + ".zip"));
    createZipFrom(new File(dirFileName));
    zipOut.close();
  }

  void createZipFrom(File dir) throws Exception
  { if (dir.exists() && dir.canRead() && dir.isDirectory())
    { File[] files = dir.listFiles();
      if (files != null)
      { for (File file: files)
        { if (file.isDirectory()) 
          { createZipFrom(file);
          }
          else
          { String filePath = file.getPath().replace('\\', '/');
            FileInputStream in = new FileInputStream(filePath);
            zipOut.putNextEntry(new ZipEntry(filePath.substring(prefixLength)));
            int bytesRead;
            while ((bytesRead = in.read(ioBuffer)) > 0) 
            { zipOut.write(ioBuffer, 0, bytesRead);
            }
            zipOut.closeEntry();
            in.close();
          }
        }
      }
    }
  }
  
  public static void main(String[] args) throws Exception
  { // Dir-Name mit "/" und ohne Ende-"/" angeben
    String dirFileName  = "C:/temp/TestArchiv";
    new DirectoryZipper(dirFileName);
  }
}

Dateien vom Java CLASSPATH lesen

Wenn Sie zur Auslieferung Ihrer Java Programme auch alle Resourcen wie Konfigurationsdateien, Images, etc. in eine .jar Datei packen, müssen Sie auch die Möglichkeit haben, auf diese Resourcen aus den Programmen heraus zuzugreifen. In den folgenden Beispielen soll gezeigt werden, wie Textdaten und Images aus Dateien, die sich auf dem Klassenpfad befinden, gelesen werden können. Um diese Beispiele nachvollziehen zu können, wird davon ausgegangen, dass sich die Java ToolbarButtonGraphics-Datei jlfgr-1_0.jar zur Laufzeit auf dem CLASSPATH befindet.

Wichtig beim Zugriff auf Resourcen ist, dass der Pfad zu den Dateien mit einem "/" beginnt und alle Pfad-Abschnitte durch "/" separiert werden.

Den notwendigen InputStream zum auslesen der Daten bekommt man über die class Variable einer beliebigen Java Klasse.

Auslesen einer Text-Resource

import java.io.*;

public class ResourceReader1 
{ public static void main(String[] args) throws IOException
  { System.out.println(getFileResource("/LICENSE"));
  }
  
  static String getFileResource(String resourceName) throws IOException
  { StringBuffer content = new StringBuffer();
    String line;
    InputStream rs = Class.class.getResourceAsStream(resourceName);
    BufferedReader in = new BufferedReader(new InputStreamReader(rs, "UTF-8"));
    while((line = in.readLine()) != null) content.append(line).append("\n");
    in.close();
    return content.toString();
  }
}

Auslesen einer Image-Resource

import java.awt.*;
import java.io.*;

public class ResourceReader2 
{ public static void main(String[] args) throws IOException
  { System.out.println(getImageResource(
      "/toolbarButtonGraphics/general/About16.gif"));
  }
  
  static Image getImageResource(String resourceName) throws IOException
  { int bytesRead;
    byte[] ioBuf = new byte[4096];
    InputStream rs = Class.class.getResourceAsStream(resourceName);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    while ((bytesRead = rs.read(ioBuf)) != -1) bos.write(ioBuf, 0, bytesRead);
    bos.close();
    rs.close();
    return Toolkit.getDefaultToolkit().createImage(bos.toByteArray());
  }
}