Java SE 8 Standard-Bibliothek  
Professionelle Bücher. Auch für Einsteiger.
 
Inhaltsverzeichnis

Vorwort
1 Neues in Java 8 und Java 7
2 Fortgeschrittene String-Verarbeitung
3 Threads und nebenläufige Programmierung
4 Datenstrukturen und Algorithmen
5 Raum und Zeit
6 Dateien, Verzeichnisse und Dateizugriffe
7 Datenströme
8 Die eXtensible Markup Language (XML)
9 Dateiformate
10 Grafische Oberflächen mit Swing
11 Grafikprogrammierung
12 JavaFX
13 Netzwerkprogrammierung
14 Verteilte Programmierung mit RMI
15 RESTful und SOAP-Web-Services
16 Technologien für die Infrastruktur
17 Typen, Reflection und Annotationen
18 Dynamische Übersetzung und Skriptsprachen
19 Logging und Monitoring
20 Sicherheitskonzepte
21 Datenbankmanagement mit JDBC
22 Java Native Interface (JNI)
23 Dienstprogramme für die Java-Umgebung
Stichwortverzeichnis

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java SE 8 Standard-Bibliothek von Christian Ullenboom
Das Handbuch für Java-Entwickler
Buch: Java SE 8 Standard-Bibliothek

Java SE 8 Standard-Bibliothek
Pfeil 9 Dateiformate
Pfeil 9.1 Einfache Dateiformate für strukturierte Daten
Pfeil 9.1.1 Property-Dateien mit java.util.Properties lesen und schreiben
Pfeil 9.1.2 CSV-Dateien
Pfeil 9.1.3 JSON-Serialisierung mit Jackson
Pfeil 9.2 Dokumentenformate
Pfeil 9.2.1 (X)HTML
Pfeil 9.2.2 PDF-Dokumente
Pfeil 9.2.3 Microsoft Office-Dokumente
Pfeil 9.2.4 OASIS Open Document Format
Pfeil 9.3 Datenkompression *
Pfeil 9.3.1 Java-Unterstützung beim Komprimieren
Pfeil 9.3.2 Daten packen und entpacken
Pfeil 9.3.3 Datenströme komprimieren
Pfeil 9.3.4 ZIP-Archive
Pfeil 9.3.5 JAR-Archive
Pfeil 9.4 Bildformate
Pfeil 9.5 Audiodateien
Pfeil 9.5.1 Die Arbeit mit Applets AudioClip
Pfeil 9.5.2 AudioClip von JavaFX
Pfeil 9.5.3 MIDI-Dateien abspielen
Pfeil 9.5.4 ID-Tags aus mp3-Dateien
 
Zum Seitenanfang

9Dateiformate Zur vorigen ÜberschriftZur nächsten Überschrift

»Ein Gramm Information wiegt schwerer als tausend Tonnen Meinung.«
– Gerd Bacher (*1925)

Beim Austausch von Dokumenten ist das Dateiformat entscheidend, damit die Darstellung und Wiedergabe optimal gelingt. Bei jedem Dokument – sei es binär oder textuell, eine Grafik oder eine Musikdatei – muss das Format der Zeichen oder Bytes definiert sein, damit das Einlesen und die Verarbeitung möglich sind. Die Definition vom Format ist je nachdem offen beschrieben (wie bei XML, PNG, OpenDocument), proprietär, aber dokumentiert (RTF, DOC) oder auch intern nur den Unternehmen bekannt (wie das Skype-Datenformat).

Einige Textformate sind gleichzeitig Auszeichnungssprachen, denn wenn alles Text ist, muss irgendwie unterschieden werden, was Auszeichnungen sind und was die eigentliche Information ist. Bei XML zum Beispiel stehen die Auszeichnungen in spitzen Klammern. Die bekannteste Auszeichnungssprache ist sicherlich HTML; Akademikern war oder ist TeX vertraut. Mittlerweile sind viele moderne Auszeichnungssprachen XML-basiert. Dazu zählen DocBook für Dokumentationen, Atom für Web-Feeds, ebXML für elektronische Geschäftsprozesse, MathML für mathematische Formeln, OpenDocument und Office Open XML (die jedoch in einem ZIP-Archiv standardmäßig komprimiert werden).

Oft gehen Betriebssysteme über die Dateiendung, um den Typ bzw. das Format einer Datei herauszulesen, oder nutzen spezielle Metadaten bzw. interpretieren die ersten Bytes, um das Format zu erkennen. Wenn Dokumente etwa in einer Datenbank abgelegt oder vom Webserver verschickt werden, haben sie keinen Dateinamen, und so werden zusätzliche Metadaten gespeichert. Im Internet beschreibt der MIME-Typ die Mediendaten. NIO.2 kann versuchen, den MIME-Typ zu ermitteln.

Da die Grundlage jedes Dokuments ein Byte ist, lässt sich natürlich immer ein Bytestrom öffnen und lassen sich die Daten selbst verarbeiten. Wir suchen jedoch eine andere, höhere Abstraktion. Die fängt schon in Java selbst damit an, dass Textdokumente nicht mit InputStream/OutputStream verarbeitet und die Strings dann von Hand in Unicode konvertiert werden, sondern dass ein Reader/Writer die Arbeit verrichtet. Wenn wir es mit XML-Dateien zu tun haben, so holen wir uns auch keinen Reader zum Lesen, sondern greifen auf elegante XML-Klassen zurück, die uns die Arbeit beim Lesen der Elemente abnehmen.

Dieses Kapitel stellt unterschiedliche Aspekte mit Dateiformaten und Java heraus. Zum einen werden unterschiedliche Dateien und Dokumentenformate vorgestellt, und zum anderen werden auch Aspekte wie Darstellung, Wiedergabe und Konvertierung angesprochen.

 
Zum Seitenanfang

9.1Einfache Dateiformate für strukturierte Daten Zur vorigen ÜberschriftZur nächsten Überschrift

Daten sind in der Regel immer strukturiert. Diese Strukturierung bekommen die Daten durch das Format oder eingebettete besondere Symbole bzw. Symbolfolgen. Das kann etwa ein Zeilenumbruchzeichen sein oder ein Token-Separator wie »=« oder XML für hierarchische Dokumente.

 
Zum Seitenanfang

9.1.1Property-Dateien mit java.util.Properties lesen und schreiben Zur vorigen ÜberschriftZur nächsten Überschrift

Dateien, die Schlüssel-Wert-Paare als String repräsentieren und die Schlüssel und Wert durch ein Gleichheitszeichen trennen, nennen sich Property-Dateien. Sie kommen zur Programmkonfiguration häufig vor, und Java bietet mit der Klasse Properties die Möglichkeit, die Property-Dateien einzulesen und zu schreiben. In Kapitel 4, »Datenstrukturen und Algorithmen«, kam die Klasse mit Beispielen schon zur Sprache.

store() und load()-Methoden vom Properties-Objekt

Die Methode store(…) dient dem Speichern der Zustände und load(…) dem Initialisieren eines Properties-Objekts aus einem Datenstrom. Die Schlüssel und Werte trennt ein Gleichheitszeichen. Die Lade-/Speichermethoden sind:

class java.util.Properties
extends Hashtable<Object,Object>
  • void store(OutputStream out, String comments)

  • void store(Writer writer, String comments)
    Schreibt die Properties-Liste in den Ausgabestrom. An den Kopf der Datei kann ein Kommentar gesetzt werden, wenn das Argument comments nicht null ist; bei null kommt kein eigener Kommentar.

  • void load(InputStream inStream)

  • void load(Reader reader) throws IOException
    Liest eine Properties-Liste aus einem Eingabestrom.

Ist der Typ ein Binärstrom also OutputStream/InputStream, so behandeln die Methoden die Zeichen in der ISO-8859-1-Kodierung. Reader/Writer erlauben eine freie Kodierung. Eine ähnliche Methode list(…) ist nur für Testausgaben gedacht, sie sollte nicht mit store(…) verwechselt werden.

Das folgende Beispiel initialisiert ein Properties-Objekt mit den Systemeigenschaften und fügt dann einen Wert hinzu. Anschließend macht store(…) die Daten persistent, load(…) liest sie wieder, und list(…) gibt die Eigenschaften auf dem Bildschirm aus:

Listing 9.1com/tutego/insel/util/map/SaveProperties.java, main()

Path path = Paths.get( "properties.txt" );

try ( Writer writer = Files.newBufferedWriter( path, StandardCharsets.UTF_8 ) ) {
Properties prop1 = new Properties( System.getProperties() );
prop1.setProperty( "MeinNameIst", "Forrest Gump" );
prop1.store( writer, "Eine Insel mit zwei Bergen" );

try ( Reader reader = Files.newBufferedReader( path, StandardCharsets.UTF_8 ) ) {
Properties prop2 = new Properties();
prop2.load( reader );
prop2.list( System.out );
}
}
catch ( IOException e ) {
e.printStackTrace();
}

Besonderheiten des Formats

Beginnt eine Zeile mit einem »#« oder »!«, gilt sie als Kommentar und wird überlesen. Da der Schlüssel selbst aus einem Gleichheitszeichen bestehen kann, steht in dem Fall ein »\« voran, folglich liefert Properties p = new Properties(); p.setProperty("=", "="); p.store(System.out, null); neben dem Kommentar die Zeile »\==\=«. Beim Einlesen berücksichtigen die Lesemethoden auch Zeilenumbrüche: Eine Zeile darf mit »\« enden, und dann führt die folgende Zeile die vorangehende fort. Die Property »cars« ist also »Honda, Mazda, BMW«, wenn steht:

cars = \
Honda, Mazda, \
BMW

Properties im XML-Format speichern

Die Properties-Klasse kann die Eigenschaften auch im XML-Format speichern und laden. Dem Speichern dienen zwei überladene Methoden storeToXML(…), und das Laden übernimmt loadFromXML(…). Das XML-Format hat einen festen Aufbau, wie es der Einzeiler System.getProperties().storeToXML(System.out, ""); zeigt:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment/>
<entry key="java.runtime.name">Java(TM) SE Runtime Environment</entry>

<entry key="sun.cpu.isalist">amd64</entry>
</properties>

Die Methode loadFromXML(…) liest aus einem InputStream und löst im Fall eines fehlerhaften Dateiformats eine InvalidPropertiesFormatException aus. Beim Speichern kann so ein Fehler natürlich nicht auftreten. Und genauso, wie bei store(…) ein OutputStream mit einem Kommentar gespeichert wird, macht das auch storeToXML(…). Die Methode ist mit einem zusätzlichen Parameter überladen, der eine XML-Kodierung erlaubt. Ist der Wert nicht gesetzt, so ist die Standardkodierung UTF-8.

class java.util.Properties
extends Hashtable<Object,Object>
  • void store(OutputStream out, String header)
    Speichert die Properties-Liste mithilfe des Ausgabestroms ab. Am Kopf der Datei wird eine Kennung geschrieben, die im zweiten Argument steht. Die Kennung darf null sein.

  • void load(InputStream inStream)
    Lädt eine Properties-Liste aus einem Eingabestrom.

  • void storeToXML(OutputStream os, String comment, String encoding) throws IOException
    Speichert die Properties im XML-Format. comment kann null sein, wenn ein Kommentar erwünschst ist. encoding steht für die Zeichenkodierung, etwa »Latin-1« oder »UTF-8«.

  • void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException
    Liest Properites im XML-Format von einem Eingabestrom ein.

 
Zum Seitenanfang

9.1.2CSV-Dateien Zur vorigen ÜberschriftZur nächsten Überschrift

Eine CSV-(Comma-separated-Values-)Datei bildet die Zeilen und Spalten einer Tabelle in einer ASCII-Datei ab. Die Zellen sind dabei durch ein Komma oder ein anderes Trennzeichen separiert. Texte können in Anführungszeichen gesetzt werden, um etwa Weißraum zu berücksichtigen.

Rodney,King,"Fahrer"
Bryant,Allen,"Gast auf dem Rücksitz"

Auch Microsoft Excel kann Tabellen in das CSV-Format exportieren, nutzt aber in der deutschen Version als Trenner ein Semikolon – CSV wird bei Microsoft also zu einer sprachabhängigen Datei (außer der Export wird über ein englischsprachiges Makro angestoßen, da ist es wieder ein Komma). In der ersten Zeile stehen die Tabellenköpfe.

Sollten CSV-Dateien in Java verarbeitet werden, fallen einem zum Einlesen spontan die Klassen Scanner und vielleicht StringTokenizer ein, allerdings sind diese zum Einlesen nicht besonders gut geeignet. Welches Trennsymbol sollte gewählt werden? Sicherlich das Semikolon. Doch was passiert, wenn dieses im Text vorkommt? Dann wird der Text in zwei Tokens aufgeteilt – was falsch ist. Des Weiteren kann der Java-StringTokenizer nicht mit Leer-Strings umgehen, also auf Zeilenfolgen wie ;; im Datenstrom reagieren; er würde sie überlesen, aber nicht einen leeren String zurückgeben.

Die Java-Standardbibliothek hilft bei CSV-Daten nicht weiter, wohl aber diverse quelloffene Bibliotheken.

Ostermiller Java Utilities

Eine freie Java-Bibliothek stammt von Stephen Ostermiller unter http://tutego.de/go/ostermillercsv. Mit dem CSVParser lassen sich leicht CSV-Daten einlesen, und er behandelt auch Fluchtsymbole korrekt.

[zB]Beispiel

Lies aus einem Eingabestrom die CSV-Daten, und gib Element für Element auf der Konsole aus:

CSVParser csvParser = new CSVParser( inputStream );
for ( String s; (s = csvParser.nextValue()) != null; )
System.out.println( csvParser.lastLineNumber() + " " + s );

Jsefa (Java Simple Exchange Format API)

Der Reiz der freien Bibliothek Jsefa (http://jsefa.sourceforge.net/) liegt in der Abbildung von Objekten auf das Datenformat, wobei Annotationen die Daten beschreiben.

[zB]Beispiel

Annotiere eine Person, und Jsefa soll ein Objekt auf das CSV-Format abbilden und zurückkonvertieren. Beispiel aus dem Tutorial[ 88 ](http://jsefa.sourceforge.net/quick-tutorial.html):

@CsvDataType()
public class Person {
@CsvField(pos = 1)
String name;
@CsvField(pos = 2, format = "dd.MM.yyyy")
Date birthDate;
}

Geschrieben wird auf diese Weise:

Serializer serializer = CsvIOFactory.createFactory(Person.class).createSerializer();
serializer.open( writer ); // so oft ausführen wie Objekte vorhanden sind
serializer.close( true );

Zum Einlesen Folgendes:

Deserializer deserializer = CsvIOFactory.createFactory(Person.class).createDeserializer();
StringReader reader = new StringReader( writer.toString() );
deserializer.open( reader );
while ( deserializer.hasNext() ) {
Person p = deserializer.next();

}
deserializer.close( true );
 
Zum Seitenanfang

9.1.3JSON-Serialisierung mit Jackson Zur vorigen ÜberschriftZur nächsten Überschrift

Im Internet hat JSON das XML-Format zwecks Objektübertragung zwischen Server und Browser fast vollständig verdrängt. Das liegt daran, dass ein Browser JSON-Strings direkt in JavaScript-Objekte konvertieren kann, XML-Dokumente aber erst aufwändiger verarbeitet werden müssen. Neben dem Einsatzgebiet im Internet bietet JSON auch ein kompaktes Format, um etwa lokale Konfigurationsdateien zu kodieren.

Nehmen wir folgende Zeile JavaScript-Code, die ein Person-Objekt mit zwei Properties für Name und Alter definiert. Eine Property wird über ein Schlüssel-Wert-Paar beschrieben:

var person = { "name" : "Michael Jackson", "age" : 50 };

Die Definition eines Objekts geschieht in der JSON (JavaScript Object Notation). Als Datentypen unterstützt JSON Zahlen, Wahrheitswerte, Strings, Arrays, null und Objekte – wie unser Beispiel zeigt. Die Deklarationen können geschachtelt sein, um Unterobjekte aufzubauen.

Zum Zugriff auf die JSON-Daten kommt der Punkt zum Einsatz, sodass der Name nach der Auswertung durch person.name zugänglich ist.

Eine Personenbeschreibung wie diese kann auch in einem String stehen, der von JavaScript zur Laufzeit ausgewertet wird.

var json = 'person = { "name" : "Michael Jackson", "age" : 50 };';
eval( json );

Der Zugriff auf person.name liefert wie vorher den Namen, denn nach der Auswertung mit eval(…) wird JavaScript ein neues Objekt mit person im Kontext anlegen.

JSON ist besonders praktisch, wenn es darum geht, Daten zwischen einem Server und einem Browser mit JavaScript-Interpreter auszutauschen. Denn wenn der String json nicht von Hand mit einem String initialisiert wurde, sondern ein Server die Zeichenkette person = { ... }; liefert, haben wir das, was heutzutage in modernen Ajax-Webanwendungen passiert. Die letzte Frage ist nun, wie elegant der Server Zeichenketten im Datenaustauschformat JSON erzeugt und so Objekte überträgt. Den String per Hand aufzubauen ist eine Lösung, aber es geht besser.

JSON-Verarbeitung mit JSON

Die Open-Source-Bibliothek Jackson (http://tutego.de/go/jackson) gehört zu den populärsten Lösungen. Sie liest JSON-Daten ein, gibt sie aus und überträgt sie auf JavaBeans, sodass eine unkomplizierte Serialisierung in JSON möglich wird:

ObjectMapper mapper = new ObjectMapper();
MyClass myObject = mapper.readValue( input, MyClass.class );
mapper.writeValue( output, myObject );

Der ObjectMapper übernimmt das Lesen/Schreiben. In der zweiten Zeile wird aus der Eingabequelle input gelesen und ein Objekt vom Typ MyClass rekonstruiert. In der dritten Zeile wird es in die Ausgabe output geschrieben.

JSON mit JavaScript-Engine von Java

Praktischerweise liefert jede (aktuelle) Java-Installation eine JavaScript-Engine mit aus, und so lassen sich JSON-Daten auch direkt über die Java-API einlesen. In Kapitel 18, »Dynamische Übersetzung und Skriptsprachen«, kommt das genauer zur Sprache, daher hier nur kurz ein Beispiel:

[zB]Beispiel

Ein String enthält JSON-kodierte Daten. Dieser wird von der JavaScript-Engine eingelesen und dann ein Element erfragt. Es bedarf wenig Fantasie, sich die Daten aus einer Datei vorzustellen und hier die Flexibilität für Konfigurationsdateien zu erkennen:

Listing 9.2com/tutego/insel/json/JavaSciptJSONDemo.java

ScriptEngine engine = new ScriptEngineManager().getEngineByName( "JavaScript" );
engine.eval( "person = { 'name' : 'Michael Jackson', 'age' : 2*25 }" );
JSObject obj = (JSObject) engine.get( "person" );
System.out.println( obj.getMember( "age" ) ); // 50

 


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java SE 8 Standard-Bibliothek Java SE 8 Standard-Bibliothek
Jetzt Buch bestellen

 Buchempfehlungen
Zum Rheinwerk-Shop: Java ist auch eine Insel
Java ist auch eine Insel


Zum Rheinwerk-Shop: Professionell entwickeln mit Java EE 8
Professionell entwickeln mit Java EE 8


Zum Rheinwerk-Shop: Besser coden
Besser coden


Zum Rheinwerk-Shop: Entwurfsmuster
Entwurfsmuster


Zum Rheinwerk-Shop: IT-Projektmanagement
IT-Projektmanagement


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2018. Original - https://www.rheinwerk-verlag.de/openbook/
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 

 
 


19.03.2024 - Sitemap.xml