Archiv für die Kategorie ‘Apache Commons’

(De-)Serialisation von Objekten in einen String (Base64 encoded)

Dienstag, 23. Juni 2009

Da es in Java keine direkte Möglichkeit gibt Binärdaten in einen String zu schreiben, kann man hierzu auf die Apache Commons Bibliothek codec zurück greifen.

Diese bietet unteranderem auch eine BASE64-Konvertierung an, die die Datenmenge zwar um ca. 33% größer werden, dann aber problemlos als Zeichenkette weiterverarbeiten lässt.

Im folgenden Beispiel wird ein konkreter Anwendungsfall gezeigt, im dem ein Objekt der Klasse SerienTerminForm mittels ObjectOutputStream serialisiert wird, bevor aus den BASE64-kodierten Daten ein neuer String erzeugt wird.

Natürlich lässt sich die Objekt-Serialisierung auch auf jede andere Klasse anpassen, die die Schnittstelle Serializable implementiert.

        /**
         * @param form
         *            the form data to serialize
         * @return the serialized string (Base64 encoded)
         */
        public static String serializeInfo(final SerienTerminForm form) {
            try {
                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                final ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(form);
                final String info = new String(new Base64().encode(baos.toByteArray()));
                return info;
            } catch (Exception e) {
                LOGGER.warn("SerienTerminForm not serializable");
                return null;
            }
        }

Hier nun auch der Rückweg aus den in der Zeichenkette gespeicherten Objektinformationen wieder eine lauffähige Instanz zu machen. In diesem Beispiel werden auftretende Ausnahmen nur abgefangen und geloggt, aber immer eine Objekt-Instanz erzeugt.

        /**
         * @param info
         *            the serialized string (Base64 encoded)
         * @return a {@link SerienTerminForm} instance (<code>null</code>-safe)
         */
        public static SerienTerminForm deserializeInfo(final String info) {
            SerienTerminForm form;
            try {
                byte[] bytes = new Base64().decode(info.getBytes());
                final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
                form = (SerienTerminForm) ois.readObject();
            } catch (Exception e) {
                LOGGER.warn("SerienTerminForm not deserializable", e);
                form = new SerienTerminForm();
            }
            return form;
        }

Hendrik Lange


Apache Commons-IO im praktischen Einsatz

Montag, 08. September 2008

Die Projekte aus der Apache Commons Reihe erleichtern dem Programmierer oft den Alltag, da sie für sehr viele Situationen Standardroutinen anbieten.

Hier wollen wir uns einige Anwendungsbeispiele der Commons IO Util-Klassen anschauen. Die gängigsten sind hier FileUtils, IOUtils und FilenameUtils.

Beim Umgang mit Textdateien z.B. XML ist das Encoding beim einlesen und schreiben von großer Bedeutung. Ansonsten werden Umlaute und Sonderzeichen nicht richtig dargestellt. Commons IO bietet hierfür viele read/write Methoden mit optionaler Angabe des Encoding an.
Zum Thema Encoding wird sicherlich noch ein extra Blog folgen: ein Gebiet, dass einen bei sämtlichen Datei-, Datenbank- usw. Zugriffen verfolgt.

Textdatei in einen String einlesen

Die Methode FileUtils.readFileToString liefert den Textinhalt einer Datei als String oder einen leeren String (nicht null). Im Fehlerfall wird eine java.io.IOException geworfen.

// use system default encoding
String text = FileUtils.readFileToString(
    new File("text.txt"));
// set encoding to UTF-8
String textUTF8 = FileUtils.readFileToString(
    new File("text-utf8.txt"),
    org.apache.commons.lang.CharEncoding.UTF_8);

Binärdatei einlesen

Ebenso einfach lässt sich eine Binärdatei einlesen.

byte[] bytes = FileUtils.readFileToByteArray(
    new File("file.bin"));

String als Textdatei speichern

Das Speichern einer Textdatei wird zum Einzeiler:

String content = "Das ist ein Text";
FileUtils.writeStringToFile(new File("text.txt"), content);

Mit Angabe des Encoding (UTF-8):

String content = "Das ist ein Text mit Umlauten: äöü ÄÖÜ";
FileUtils.writeStringToFile(new File("text.txt"), content,
    org.apache.commons.lang.CharEncoding.UTF_8);

Als Variation kann noch eine Collection in eine Textdatei geschrieben werden:

List lines = new ArrayList();
// befüllen der List ...
FileUtils.writeLines(new File("lines.txt"), lines);

Analog funktioniert das Ganze genau so einfach mit Binärdateien.

Dateiliste anhand der Endung erstellen

Anwendungsfall: In einem Verzeichnis liegen viele XML und PDF Dateien. Nun sollen alle XML Dateien nacheinander geparsed werden. Die Methode FileUtils.listFiles erwartet als Parameter das Verzeichnis, in dem sich die Dateien befinden. Ein Array der Dateiendungen, die eingelesen werden sollen. Ein Flag ob das Verzeichnis rekursiv durchsucht werden soll.

Collection files = FileUtils.listFiles(
    new File("/dir"),
    new String [] {"xml"},
    false);
for (File file : files) {
    // parse file
}

Textdatei Zeilenweise auslesen

Anwendungsfall: Eine csv Datei wird Zeilenweise eingelesen und verarbeitet.

List lines = FileUtils.readLines(
    new File("data.csv"),
    org.apache.commons.lang.CharEncoding.UTF_8);
for (String string : lines) {
    // process single line
}

Streams/Reader/Writer schliessen

Auch ein sehr häufiger Anwendungsfall ist das Schließen von Streams usw.
wobei vorher auf Null geprüft wird und eine Exception gefangen und in der
Regel ignoriert wird.

Vorher:

Writer writer = null;
try {
    writer = new FileWriter("filename.txt");
    // ...
} catch (Exception e) {
    // handle exception
} finally {
    if (writer != null) {
        try {
            writer.close();
        } catch (IOException e) {
            // ignore
        }
    }
}

Nachher:

Writer writer = null;
try {
    writer = new FileWriter("filename.txt");
    // ...
} catch (Exception e) {
    // handle exception
} finally {
    IOUtils.closeQuietly(writer);
}

IOUtils Kurzübersicht

Weitere Methoden der IOUtlis dienen u.A. zum vergleichen und kopieren von Dateien,
erzeugen von Streams und schreiben in Streams.

FilenameUtils Kurzübersicht

Wie der Name erahnen lässt dienen die Methoden dieser Klasse zur Auswertung und Manipulation
von Dateiname. Häufig verwendet:

FilenameUtils.getBaseName(filename);
FilenameUtils.getExtension(filename);
FilenameUtils.removeExtension(filename);

Ein Blick in die Javadocs lohnt sich hier auf alle Fälle.

Viel Spaß und Erfolg beim Ausprobieren und Anwenden.


Christof Aenderl