Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger. 
Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Eigene Klassen schreiben
6 Objektorientierte Beziehungsfragen
7 Ausnahmen müssen sein
8 Äußere.innere Klassen
9 Besondere Typen der Java SE
10 Generics<T>
11 Lambda-Ausdrücke und funktionale Programmierung
12 Architektur, Design und angewandte Objektorientierung
13 Komponenten, JavaBeans und Module
14 Die Klassenbibliothek
15 Einführung in die nebenläufige Programmierung
16 Einführung in Datenstrukturen und Algorithmen
17 Einführung in grafische Oberflächen
18 Einführung in Dateien und Datenströme
19 Einführung ins Datenbankmanagement mit JDBC
20 Einführung in <XML>
21 Testen mit JUnit
22 Bits und Bytes und Mathematisches
23 Die Werkzeuge des JDK
A Java SE-Paketübersicht
Stichwortverzeichnis


Download:

- Beispielprogramme, ca. 35,4 MB


Buch bestellen
Ihre Meinung?



Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom

Einführung, Ausbildung, Praxis
Buch: Java ist auch eine Insel


Java ist auch eine Insel

Pfeil 14 Die Klassenbibliothek
Pfeil 14.1 Die Java-Klassenphilosophie
Pfeil 14.1.1 Übersicht über die Pakete der Standardbibliothek
Pfeil 14.1.2 Compact-Profile
Pfeil 14.2 Sprachen der Länder
Pfeil 14.2.1 Sprachen und Regionen über Locale-Objekte
Pfeil 14.3 Die Klasse Date
Pfeil 14.3.1 Objekte erzeugen und Methoden nutzen
Pfeil 14.3.2 Date-Objekte sind nicht immutable
Pfeil 14.4 Calendar und GregorianCalendar
Pfeil 14.4.1 Die abstrakte Klasse Calendar
Pfeil 14.4.2 Calendar nach Date und Millisekunden fragen
Pfeil 14.4.3 Abfragen und Setzen von Datumselementen über Feldbezeichner
Pfeil 14.4.4 Kalender-Exemplare bauen über den Calendar.Builder
Pfeil 14.4.5 Der gregorianische Kalender
Pfeil 14.4.6 Date-Time-API
Pfeil 14.4.7 Menschenzeit und Maschinenzeit
Pfeil 14.5 Die Utility-Klasse System und Properties
Pfeil 14.5.1 Systemeigenschaften der Java-Umgebung
Pfeil 14.5.2 Zeilenumbruchzeichen, line.separator
Pfeil 14.5.3 Eigene Properties von der Konsole aus setzen *
Pfeil 14.5.4 Umgebungsvariablen des Betriebssystems *
Pfeil 14.5.5 Einfache Zeitmessung und Profiling *
Pfeil 14.6 Einfache Benutzereingaben
Pfeil 14.6.1 Grafischer Eingabedialog über JOptionPane
Pfeil 14.6.2 Geschützte Passwort-Eingaben mit der Klasse Console *
Pfeil 14.7 Benutzereinstellungen *
Pfeil 14.7.1 Benutzereinstellungen mit der Preferences-API
Pfeil 14.7.2 Einträge einfügen, auslesen und löschen
Pfeil 14.7.3 Auslesen der Daten und Schreiben in einem anderen Format
Pfeil 14.7.4 Auf Ereignisse horchen
Pfeil 14.7.5 Zugriff auf die gesamte Windows-Registry
Pfeil 14.8 Zum Weiterlesen
 

Zum Seitenanfang

14.7Benutzereinstellungen * Zur vorigen ÜberschriftZur nächsten Überschrift

Einstellungen des Benutzers – wie die letzten vier geöffneten Dateien oder die Position eines Fensters – müssen abgespeichert und erfragt werden können. Dafür bietet Java eine Reihe von Möglichkeiten. Sie unterscheiden sich unter anderem in dem Punkt, ob die Daten lokal beim Benutzer oder zentral auf einem Server abgelegt sind.

Im lokalen Fall lassen sich die Einstellungen zum Beispiel in einer Datei speichern. Das Dateiformat kann in Textform oder binär sein. In Textform lassen sich die Informationen etwa in der Form Schlüssel=Wert oder im XML-Format ablegen. Werden Datenstrukturen mit den Benutzereinstellungen serialisiert, kommen in der Regel binäre Dateien heraus. Unter Windows gibt es eine andere Möglichkeit der Speicherung: die Registry. Auch sie ist eine lokale Datei, nur kann das Java-Programm keinen direkten Zugriff auf die Datei vornehmen, sondern muss über Betriebssystemaufrufe Werte einfügen und erfragen.

Sollen die Daten nicht auf dem Benutzerrechner abgelegt werden, sondern zentral auf einem Server, so gibt es auch verschiedene Standards. Die Daten können zum Beispiel über einen Verzeichnisdienst oder Namensdienst verwaltet werden. Bekanntere Dienste sind hier LDAP oder Active Directory. Zum Zugriff auf die Dienste lässt sich das Java Naming and Directory Interface (JNDI) einsetzen. Natürlich können die Daten auch in einer ganz normalen Datenbank stehen, auf die dann die eingebaute JDBC-API Zugriff gewährt. Bei den letzten beiden Formen können die Daten auch lokal vorliegen, denn eine Datenbank oder ein Server, der über JDNI zugänglich ist, kann auch lokal sein. Der Vorteil von nichtlokalen Servern ist einfach der, dass sich der Benutzer flexibler bewegen kann und immer Zugriff auf seine Daten hat.

Zu guter Letzt lassen sich Einstellungen auch auf der Kommandozeile übergeben. Das lässt die Option -D auf der Kommandozeile zu, wenn das Dienstprogramm java die JVM startet. Nur lassen sich dann die Daten nicht einfach vom Programm ändern, aber zumindest lassen sich so sehr einfach Daten an das Java-Programm übertragen.

 

Zum Seitenanfang

14.7.1Benutzereinstellungen mit der Preferences-API Zur vorigen ÜberschriftZur nächsten Überschrift

Mit der Klasse java.util.prefs.Preferences können Konfigurationsdateien gespeichert und abgefragt werden. Für die Benutzereinstellungen stehen zwei Gruppen zur Verfügung: die Benutzerumgebung und die Systemumgebung. Die Benutzerumgebung ist individuell für jeden Benutzer (jeder Benutzer hat andere Dateien zum letzten Mal geöffnet), aber die Systemumgebung ist global für alle Benutzer. Je nach Betriebssystem verwendet die Preferences-Implementierung unterschiedliche Speichervarianten und Orte:

  • Unter Windows wird dazu ein Teilbaum der Registry reserviert. Java-Programme bekommen einen Zweig, SOFTWARE\JavaSoft\Prefs unter HKEY_LOCAL_MACHINE und HKEY_CURRENT_USER, zugewiesen. Es lässt sich nicht auf die gesamte Registry zugreifen!

  • Unix und Mac OS X speichern die Einstellungen in XML-Dateien. Die Systemeigenschaften landen bei Unix unter /etc/.java/.systemPrefs und die Benutzereigenschaften lokal unter $HOME/.java/.userPrefs. Mac OS X speichert Benutzereinstellungen im Verzeichnis /Library/Preferences/.

Erfragen der Ausgangsobjekte Preferences

Preferences-Objekte lassen sich über statische Methoden auf zwei Arten erlangen:

  • Die erste Möglichkeit nutzt einen absoluten Pfad zum Registry-Knoten. Die Methoden sind am Preferences-Objekt befestigt und heißen für die Benutzerumgebung userRoot() und für die Systemumgebung systemRoot().

  • Die zweite Möglichkeit nutzt die Eigenschaft, dass automatisch jede Klasse in eine Paketstruktur eingebunden ist. userNodeForPackage(Class) oder systemNodeForPackage(Class) liefern ein Preferences-Objekt für eine Verzeichnisstruktur, in der die Klasse selbst liegt.

[zB]Beispiel

Erfrage ein Benutzer-Preferences-Objekt über einen absoluten Pfad und über die Paketstruktur der eigenen Klasse:

Preferences userPrefs = Preferences.userRoot().node( "/com/tutego/insel" );

Preferences userPrefs = Preferences.userNodeForPackage( this.getClass() );

Eine Unterteilung in eine Paketstruktur ist anzuraten, da andernfalls Java-Programme gegenseitig die Einstellung überschreiben könnten; die Registry-Informationen sind für alle sichtbar. Die Einordnung in das Paket der eigenen Klasse ist eine der Möglichkeiten.

abstract class java.util.prefs.Preferences
  • static Preferences userRoot()

    Liefert ein Preferences-Objekt für Einstellungen, die lokal für den Benutzer gelten.

  • static Preferences systemRoot()

    Liefert ein Preferences-Objekt für Einstellungen, die global für alle Benutzer gelten.

 

Zum Seitenanfang

14.7.2Einträge einfügen, auslesen und löschen Zur vorigen ÜberschriftZur nächsten Überschrift

Die Klasse Preferences hat große Ähnlichkeit mit den Klassen Properties und HashMap (vergleiche Kapitel 16, »Einführung in Datenstrukturen und Algorithmen«). Schlüssel/Werte-Paare lassen sich einfügen, löschen und erfragen. Allerdings ist die Klasse Preferences kein Mitglied der Collection-API, und es existiert auch keine Implementierung von Collection-Schnittstellen.

abstract class java.util.prefs.Preferences
  • abstract void put(String key, String value)

  • abstract void putBoolean(String key, boolean value)

  • abstract void putByteArray(String key, byte[] value)

  • abstract void putDouble(String key, double value)

  • abstract void putFloat(String key, float value)

  • abstract void putInt(String key, int value)

  • abstract void putLong(String key, long value)

    Bildet eine Assoziation zwischen den Schlüsselnamen und dem Wert. Die Varianten mit den speziellen Datentypen nehmen intern eine einfache String-Umwandlung vor und sind nur kleine Hilfsmethoden; so steht in putDouble(…) nur put(key, Double.toString(value)). Die Hilfsmethode putByteArray(…) konvertiert die Daten nach der Base64-Kodierung und legt sie intern als String ab.

  • abstract String get(String key, String def)

  • abstract boolean getBoolean(String key, boolean def)

  • abstract byte[] getByteArray(String key, byte[] def)

  • abstract double getDouble(String key, double def)

  • abstract float getFloat(String key, float def)

  • abstract int getInt(String key, int def)

  • abstract long getLong(String key, long def)

    Liefert den gespeicherten Wert typgerecht aus. Fehlerhafte Konvertierungen werden etwa mit einer NumberFormatException bestraft. Der zweite Parameter erlaubt die Angabe eines Alternativwerts, falls es keinen assoziierten Wert zu dem Schlüssel gibt.

  • abstract String[] keys()

    Liefert alle Knoten unter der Wurzel, denen ein Wert zugewiesen wurde. Falls der Knoten keine Eigenschaften hat, liefert keys() ein leeres Array.

  • abstract void flush()

    Die Änderungen werden unverzüglich in den persistenten Speicher geschrieben.

Unser folgendes Programm richtet einen neuen Knoten unter /com/tutego/insel ein. Aus den über System.getProperties() ausgelesenen Systemeigenschaften sollen alle Eigenschaften, die mit »user.« beginnen, in die Registry übernommen werden:

Listing 14.8com/tutego/insel/prefs/PropertiesInRegistry.java, Ausschnitt 1

static Preferences prefs = Preferences.userRoot().node( "/com/tutego/insel" );



static void fillRegistry() {

for ( Object o : System.getProperties().keySet() ) {

String key = o.toString();



if ( key.startsWith("user.") && ! System.getProperty(key).isEmpty() )

prefs.put( key, System.getProperty(key) );

}

}

Um die Elemente auszulesen, kann ein bestimmtes Element mit getXXX(…) erfragt werden. Die Ausgabe aller Elemente unter einem Knoten gelingt am besten mit keys(). Das Auslesen kann eine BackingStoreException auslösen, falls der Zugriff auf den Knoten nicht möglich ist.

Mit get(…) erfragen wir im folgenden Code den mit dem Schlüssel assoziierten Wert. Wir geben »---« aus, falls der Schlüssel keinen assoziierten Wert besitzt:

Listing 14.9com/tutego/insel/prefs/PropertiesInRegistry.java, Ausschnitt 2

static void display() {

try {

for ( String key : prefs.keys() )

System.out.println( key + ": " + prefs.get(key, "---") );

}

catch ( BackingStoreException e ) {

System.err.println( "Knoten können nicht ausgelesen werden: " + e );

}

}

[»]Hinweis

Die Größen der Schlüssel und Werte sind beschränkt! Der Knoten- und Schlüsselname darf maximal Preferences.MAX_NAME_LENGTH/MAX_KEY_LENGTH Zeichen umfassen, und die Werte dürfen nicht größer als MAX_VALUE_LENGTH sein. Die aktuelle Belegung der Konstanten gibt 80 Zeichen und 8 KiB (8.192 Zeichen) an.

Um Einträge wieder loszuwerden, gibt es drei Methoden: clear(…), remove(…) und removeNode(…). Die Namen sprechen für sich.

 

Zum Seitenanfang

14.7.3Auslesen der Daten und Schreiben in einem anderen Format Zur vorigen ÜberschriftZur nächsten Überschrift

Die Daten aus den Preferences lassen sich mit exportNode(OutputStream) oder exportSubtree(OutputStream) im UTF-8-kodierten XML-Format in einen Ausgabestrom schreiben. exportNode(OutputStream) speichert nur einen Knoten, und exportSubtree(OutputStream) speichert den Knoten inklusive seiner Kinder. Und auch der umgekehrte Weg funktioniert: importPreferences(InputStream) importiert Teile in die Registrierung. Die Schreib- und Lesemethoden lösen eine IOException bei Fehlern aus, und eine InvalidPreferencesFormatException ist beim Lesen möglich, wenn die XML-Daten ein falsches Format haben.

 

Zum Seitenanfang

14.7.4Auf Ereignisse horchen Zur vorigen ÜberschriftZur nächsten Überschrift

Änderungen an den Preferences lassen sich mit Listenern verfolgen. Zwei sind im Angebot:

  • Der NodeChangeListener reagiert auf Einfüge- und Löschoperationen von Knoten.

  • Der PreferenceChangeListener informiert bei Wertänderungen.

Es ist nicht gesagt, dass, wenn andere Applikationen die Einstellungen ändern, diese Änderungen vom Java-Programm auch erkannt werden.

Eine eigene Klasse NodePreferenceChangeListener soll die beiden Schnittstellen NodeChangeListener und PreferenceChangeListener implementieren und auf der Konsole die erkannten Änderungen ausgeben:

Listing 14.10com/tutego/insel/prefs/NodePreferenceChangeListener.java, NodePreferenceChangeListener

class NodePreferenceChangeListener implements

NodeChangeListener, PreferenceChangeListener {



@Override public void childAdded( NodeChangeEvent e ) {

Preferences parent = e.getParent(), child = e.getChild();



System.out.println( parent.name() + " hat neuen Knoten " + child.name() );

}



@Override public void childRemoved( NodeChangeEvent e ) {

Preferences parent = e.getParent(), child = e.getChild();



System.out.println( parent.name() + " verliert Knoten " + child.name() );

}



@Override public void preferenceChange( PreferenceChangeEvent e ) {

String key = e.getKey(), value = e.getNewValue();



Preferences node = e.getNode();



System.out.println( node.name() + " hat neuen Wert " + value + " für " + key );

}

}

Zum Anmelden eines Listeners bietet Preferences zwei addXXXChangeListener(…)-Methoden:

Listing 14.11com/tutego/insel/prefs/PropertiesInRegistry.java, addListener()

NodePreferenceChangeListener listener = new NodePreferenceChangeListener();

prefs.addNodeChangeListener( listener );

prefs.addPreferenceChangeListener( listener );
 

Zum Seitenanfang

14.7.5Zugriff auf die gesamte Windows-Registry Zur vorigen ÜberschriftZur nächsten Überschrift

Wird Java unter MS Windows ausgeführt, so ergibt sich hin und wieder die Aufgabe, Eigenschaften der Windows-Umgebung zu kontrollieren. Viele Eigenschaften des Windows-Betriebssystems sind in der Registry versteckt, und Java bietet als plattformunabhängige Sprache keine Möglichkeit, diese Eigenschaften in der Registry auszulesen oder zu verändern. (Die Schnittstelle java.rmi.registry.Registry ist eine Zentrale für entfernte Aufrufe und hat mit der Windows-Registry nichts zu tun. Auch das Paket java.util.prefs mit der Klasse Preferences erlaubt nur Modifikationen an einem ausgewählten Teil der Windows-Registry.)

Java kann auf unterschiedlichen Arten auf alle Teile der Windows-Registry zuzugreifen:

  • Es lässt sich eine Klasse nutzen, die Preferences unter Windows realisiert: java. util.prefs.WindowsPreferences. Damit ist keine zusätzliche native Implementierung – und damit eine Windows-DLL im Klassenpfad – nötig. Die Bibliothek http://sourceforge.net/projects/jregistrykey/ realisiert eine solche Lösung.

  • eine native Bibliothek

  • das Aufrufen des Konsolenregistrierungsprogramms reg.exe zum Setzen und Abfragen von Schlüsselwerten

Registry-Zugriff selbst gebaut

Für einfache Anfragen lässt sich der Registry-Zugriff schnell auch von Hand erledigen. Dazu bringt Windows zwei Kommandozeilenprogramme mit: regedit.exe und reg.exe. Während regedit eher ein grafisches Werkzeug ist, das aber auch Textdateien mit Registrierungsdaten schreiben kann, ist reg etwas einfacher gestrickt. Ein guter Start ist reg /?, das alle Befehle anzeigt. Interessant sind die Befehle query (Abfrage), add (Eintrag hinzufügen) und delete (Eintrag löschen). Die Abfrage, wie der Dateiname für den Desktop-Hintergrund aussieht, sieht damit so aus:

$ reg query "HKEY_CURRENT_USER\Control Panel\Desktop" /v Wallpaper



! REG.EXE VERSION 3.0



HKEY_CURRENT_USER\Control Panel\Desktop

Wallpaper REG_SZ C:\Dokumente und Einstellungen\tutego\Anwendungsdaten\Hg.bmp

Der Aufruf reg query /? liefert weitere Erklärungen.

Wenn wir reg von Java aufrufen, haben wir den gleichen Effekt:

Listing 14.12com/tutego/insel/lang/JavaWinReg.java, main()

ProcessBuilder builder = new ProcessBuilder(

"reg", "query",

"\"HKEY_CURRENT_USER\\Control Panel\\Desktop\"", "/v", "Wallpaper" );

Process p = builder.start();

try ( Scanner scanner = new Scanner( p.getInputStream() ) ) {

scanner.nextLine(); // Springe über ! REG.EXE VERSION 3.0

scanner.nextLine(); // Springe über HKEY_CURRENT_USER\Control Panel\Desktop

scanner.useDelimiter( "\\s+\\w+\\s+\\w+\\s+" );

System.out.println( scanner.next() );

}

 


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück

 

 


Copyright © Rheinwerk Verlag GmbH 2017

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.

 

[Rheinwerk Computing]



Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de