Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
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 2 Fortgeschrittene String-Verarbeitung
Pfeil 2.1 Erweitere Zeicheneigenschaften
Pfeil 2.1.1 isXXX(….)-Methoden
Pfeil 2.1.2 Unicode-Blöcke
Pfeil 2.1.3 Unicode-Skripte
Pfeil 2.2 Reguläre Ausdrücke
Pfeil 2.2.1 Pattern.matches(…) bzw. String#matches(…)
Pfeil 2.2.2 Die Klassen Pattern und Matcher
Pfeil 2.2.3 Finden und nicht matchen
Pfeil 2.2.4 Gruppen
Pfeil 2.2.5 Gierige und nicht gierige Operatoren *
Pfeil 2.2.6 Mit MatchResult alle Ergebnisse einsammeln *
Pfeil 2.2.7 Suchen und Ersetzen mit Mustern
Pfeil 2.2.8 Hangman Version 2
Pfeil 2.3 Zerlegen von Zeichenketten
Pfeil 2.3.1 Zerlegen von Zeichensequenzen über String oder Pattern
Pfeil 2.3.2 Mehr vom Scanner
Pfeil 2.3.3 Die Klasse StringTokenizer *
Pfeil 2.3.4 BreakIterator als Zeichen-, Wort-, Zeilen- und Satztrenner *
Pfeil 2.3.5 StreamTokenizer *
Pfeil 2.4 Zeichenkodierungen, XML/HTML-Entities, Base64 *
Pfeil 2.4.1 Unicode und 8-Bit-Abbildungen
Pfeil 2.4.2 Kodierungen über die Klasse String vornehmen
Pfeil 2.4.3 Das Paket java.nio.charset und der Typ Charset
Pfeil 2.4.4 Konvertieren mit OutputStreamWriter-/InputStreamReader-Klassen
Pfeil 2.4.5 XML/HTML-Entities ausmaskieren
Pfeil 2.4.6 Base64-Kodierung
Pfeil 2.5 Ausgaben formatieren
Pfeil 2.5.1 Die Formatter-Klasse *
Pfeil 2.5.2 Formatieren mit Masken *
Pfeil 2.5.3 Format-Klassen
Pfeil 2.5.4 Zahlen, Prozente und Währungen mit NumberFormat und DecimalFormat formatieren *
Pfeil 2.5.5 MessageFormat und Pluralbildung mit ChoiceFormat
Pfeil 2.6 Sprachabhängiges Vergleichen und Normalisierung *
Pfeil 2.6.1 Die Klasse Collator
Pfeil 2.6.2 Effiziente interne Speicherung für die Sortierung
Pfeil 2.6.3 Normalisierung
Pfeil 2.7 Phonetische Vergleiche *
Pfeil 2.8 Zum Weiterlesen
 
Zum Seitenanfang

2.5Ausgaben formatieren Zur vorigen ÜberschriftZur nächsten Überschrift

Ausgaben sind in Programmen alltäglich, wobei wir hierunter nicht nur die Konsolenausgaben verstehen wollen, sondern alle Umwandlungen in ein lesbares Format. In diesem Kapitel geht es um die diversen Formatierungsklassen zum Aufbereiten von Strings.

 
Zum Seitenanfang

2.5.1Die Formatter-Klasse * Zur vorigen ÜberschriftZur nächsten Überschrift

Die String.format(…)-Methode und prinf(…)-Methoden der Ein-/Ausgabeklassen übernehmen die Aufbereitung nicht selbst, sondern delegieren sie an die Klasse java.util.Formatter. Das ist auch der Grund, warum die Dokumentation für die Formatspezifizierer nicht etwa an String.format(…) hängt, sondern an Formatter.

Konstruktor vom Formatter

Die Klasse Formatter hat eine beeindruckende Anzahl an Konstruktoren:

  • Formatter()

  • Formatter(Appendable a)

  • Formatter(Appendable a, Locale l)

  • Formatter(File file)

  • Formatter(File file, String csn)

  • Formatter(File file, String csn, Locale l)

  • Formatter(Locale l)

  • Formatter(OutputStream os)

  • Formatter(OutputStream os, String csn)

  • Formatter(OutputStream os, String csn, Locale l)

  • Formatter(PrintStream ps)

  • Formatter(String fileName)

  • Formatter(String fileName, String csn)

  • Formatter(String fileName, String csn, Locale l)

Wird nicht der Standard-Konstruktor eingesetzt, schreibt der Formatter in die angegebene Quelle. Daher ist die Klasse schön für das Schreiben von Texten in Dateien geeignet. Formatter implementiert Closeable, ist also auch AutoCloseable. Ein Beispiel zum Schreiben in Dateien:

Listing 2.16WriteFormattedStringToFile.java, main()

try ( Formatter out = new Formatter( "ausgabe.txt",
StandardCharsets.ISO_8859_1.name() ) ) {
for ( int i = 0; i < 10; i++ )
out.format( "%02d%n", i );
}
catch ( FileNotFoundException | UnsupportedEncodingException e ) {
e.printStackTrace();
}

format(…)-Aufrufe optimieren

Ein Blick auf die Methode format(…) der Klasse String verrät, wie der Formatter ins Spiel kommt:

Listing 2.17java.lang.String, format()

public static String format( String format, Object... args ) {
return new Formatter().format( format, args ).toString();
}

Ein Formatter übernimmt zwei Aufgaben. Er übernimmt zum einen die tatsächliche Formatierung, und zum anderen gibt er die formatierten Ausgaben an ein Ziel weiter. Wird der Formatter mit dem Standard-Konstruktor aufgerufen, so baut er selbst das Ausgabeziel aus einem StringBuilder auf, den folgende format(…)-Aufrufe dann füllen. toString() vom Formatter ist so implementiert, dass es auf dem Ausgabeziel (also in unserem Fall dem StringBuilder) toString() aufruft.

Das Wissen um diesen Mechanismus ist für die Optimierung wichtig, um nicht zu viele Zwischenobjekte zu erzeugen. So führt die Schleife

StringBuilder sb = new StringBuilder();
for ( double d = 0; d <= 1; d += 0.1 ) {
String s = String.format( "%.1f%n", d );
sb.append( s );
}
System.out.println( sb ); // 0,1 0,2 … 1,0

zu:

StringBuilder sb = new StringBuilder();
for ( double d = 0; d <= 1; d += 0.1 ) {
String s = new Formatter().format( "%.1f%n", d ).toString();
sb.append( s );
}
System.out.println( sb ); // 0,1 0,2 … 1,0

Bei jedem Schleifendurchlauf wird also ein neuer Formatter aufgebaut. Intern entsteht damit ein neuer StringBuilder als Ziel für die formatierten Strings und schlussendlich über toString() ein String-Objekt. Nicht zu vergessen sind die internen char-Felder und die automatische Speicherbereinigung, die die Objekte wieder wegräumen muss.

Würden wir gleich das Ziel angeben, so könnte das viel effizienter werden. Dazu wird nicht der Standard-Konstruktor von Formatter eingesetzt, der das Ziel mit einem neuen StringBuilder vorbestimmt, sondern ein eigenes Zielobjekt, das unser StringBuilder sein kann (es ist alles erlaubt, was vom Typ Appendable ist). Optimiert folgt somit:

Listing 2.18FormatterDemo.java, main()

StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter( sb );

for ( double d = 0; d <= 1; d += 0.1 )
formatter.format( "%.1f%n", d );

System.out.println( formatter ); // 0,1 0,2 … 1,0

Wir weisen in der Schleife den Formatter an, die Formatierung vorzunehmen. Da dieser mit dem Ziel StringBuilder aufgebaut wurde, füllen die Zahlen nach und nach unseren StringBuilder. Temporäre Zwischenobjekte werden so minimiert. Zum Schluss wird der Formatter nach dem Ergebnis gefragt.

Formattable und formatTo(…)

Der Formatspezifizierer %s kann auf jedem Argumenttyp angewendet werden, denn durch die Varargs werden auch primitive Elemente zu Wrapper-Objekten, die eine toString()-Methode haben. Nun kann es aber sein, dass toString() besonders implementiert werden muss und nicht unbedingt die Zeichenkette liefert, die für die Ausgabe gewünscht ist. Für diesen Fall berücksichtigt der Formatter einen besonderen Typ. Implementiert die Klasse die besondere Schnittstelle java.util.Formattable, so ruft der Formatter nicht die toString()-Methode auf, sondern formatTo(Formatter formatter, int flags, int width, int precision). Die API-Dokumentation liefert ein Beispiel.

 
Zum Seitenanfang

2.5.2Formatieren mit Masken * Zur vorigen ÜberschriftZur nächsten Überschrift

Oftmals unterscheidet sich bei grafischen Oberflächen die Darstellung von Daten von dem tiefer liegenden Datenmodell. Während ein Datum zum Beispiel intern als große Zahl vorliegt, soll der Anwender sie in der gewünschten Landessprache sehen können. Bei einigen Ausgaben kommen Trennzeichen in die Ausgabe, um sie für den Leser besser verständlich zu machen. Eine IP-Adresse enthält Punkte an ganz bestimmten Stellen, eine Telefonnummer trennt die Vorwahl vom Rest ab, und die Segmente eines Datums trennen in der Regel die Zeichen »/« oder »-«.

Für Formatierungen, bei denen ein Original-String in einen Ausgabe-String konvertiert wird und dabei neue Zeichen zur Ausgabe eingefügt werden, bietet die Java-API eine Klasse javax.swing.text.MaskFormatter. Die Swing-Klasse hilft bei der Formatierung und dem Parsen:

Listing 2.19MaskFormatterDemo.java, main()

MaskFormatter mf = new MaskFormatter( "**-**-****" );
mf.setValueContainsLiteralCharacters( false );
String valueToString = mf.valueToString( "12031973" );
System.out.println( valueToString ); // 12-03-1973
Object stringToValue = mf.stringToValue( valueToString );
System.out.println( stringToValue ); // 12031973

Der Konstruktor von MaskFormatter bekommt ein Muster, wobei es Platzhalter gibt. Das Sternchen * steht für ein Zeichen. Die Methode valueToString(…) bringt einen String in das Muster. Der gemusterte String wandelt stringToValue() wieder in das Original um.

Das Schöne ist, dass die Musterdefinitionen aus einer externen Quelle stammen können, ohne den Programmcode mit speziellen Formatierungsanweisungen zu verschmutzen. Neben * gibt es weitere Platzhalter, die erlaubte Zeichen eingrenzen, sodass bei der Umwandlung mit valueToString() eine ParseException ausgelöst wird, wenn das Zeichen nicht im Format des Musterplatzhalters ist.

Musterzeichen

Steht für

*

jedes Zeichen

#

eine Zahl, wie Character.isDigit(…) sie testet

?

ein Zeichen nach Character.isLetter(…)

A

ein Zeichen oder eine Ziffer, also Character.isLetter(…) oder Character.isDigit(…)

U

ein Zeichen nach Character.isLetter(…), aber konvertiert in einen Großbuchstaben

L

ein Zeichen nach Character.isLetter(…), aber konvertiert in einen Kleinbuchstaben

H

ein Hexadezimalzeichen (0–9, a–f oder A–F)

'

einen ausmaskierten und nicht interpretierten Bereich

Tabelle 2.11Musterplatzhalter

Weitere Möglichkeiten der Klasse beschreibt die API-Dokumentation.

 
Zum Seitenanfang

2.5.3Format-Klassen Zur vorigen ÜberschriftZur nächsten Überschrift

Die Methode format(…) formatiert Zahlen, Datumswerte und sonstige Ausgaben und benötigt wegen ihrer Komplexität eine Beschreibung von mehreren Bildschirmseiten. Dabei gibt es noch eine andere Möglichkeit, für unterschiedliche Typen von zu formatierenden Werten eigene Klassen zu haben:

  • DateFormat: Formatieren von Datums-/Zeitwerten

  • NumberFormat: Formatieren von Zahlen

  • MessageFormat: Formatieren für allgemeine Programmmeldungen

Die Klassen haben gemeinsam, dass sie die abstrakte Klasse Format erweitern und so eine gemeinsame Schnittstelle haben. Jede dieser Klassen implementiert auf jeden Fall die Methode format(…) zur Ausgabe und zum Parsen, also zur Konvertierung vom String in das Zielobjekt, die Methode parseObject(…).

Zwei Gründe sprechen für den Einsatz der Format-Klassen:

  • Es gibt in String zwar eine format(…)-Methode, aber keine parseXXX(…)-Methode.

  • Die Format-Klassen liefern mit statischen getXXXInstance(…)-Methoden vordefinierte Format-Objekte, die übliche Standardausgaben erledigen, etwa gerundete Ganzzahlen, Prozente oder unterschiedlich genaue Datums-/Zeitangaben.

Das folgende Beispiel zeigt einige Anwendungen zum zweiten Punkt.

Ergebnis

Formatiert mit

02.09.2005

DateFormat.getDateInstance().format( new Date() )

15:25:16

DateFormat.getTimeInstance().format( new Date() )

02.09.2005 15:25:16

DateFormat.getDateTimeInstance().format( new Date() )

12.345,679

NumberFormat.getInstance().format( 12345.6789 )

12.345,68 €

NumberFormat.getCurrencyInstance().format( 12345.6789 )

12 %

NumberFormat.getPercentInstance().format( 0.123 )

Tabelle 2.12Formatobjekte im Einsatz

DateFormatDateFormat, Klasse, MessageFormatMessageFormat, Klasse und NumberFormatNumberFormat, Klasse erweitern die abstrakte Klasse FormatFormat, Klasse. Die Unterklassen übernehmen die Ein-/Ausgabe für Datumsangaben, für allgemeine Programmmeldungen und für Zahlen.

Abbildung 2.3DateFormat, MessageFormat und NumberFormat erweitern die abstrakte Klasse Format. Die Unterklassen übernehmen die Ein-/Ausgabe für Datumsangaben, für allgemeine Programmmeldungen und für Zahlen.

Beim Einsatz von DateFormat.getDateInstance().format(date) berücksichtigt die Methode korrekt je nach Land die Reihenfolge von Tag, Monat und Jahr und das Trennzeichen. Bei einem String.format(…) über %t müssten die drei Segmente je nach Sprache in die richtige Reihenfolge gebracht werden, sodass die Variante über DateFormat besser ist.

[»]Hinweis

NumberFormat stellt die Zahlen nicht in Exponentialschreibweise dar, und standardmäßig ist die Anzahl an Nachkommastellen beschränkt:

System.out.println( NumberFormat.getInstance().format( 2E30 ) );
System.out.println( NumberFormat.getInstance().format( 2E-30 ) );

Die Ausgabe ist:

2.000.000.000.000.000.000.000.000.000.000
0
abstract class java.text.Format
implements Serializable, Cloneable
  • String format(Object obj)
    Formatiert das Objekt obj und gibt eine Zeichenkette zurück.

  • abstract StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos)
    Formatiert ein Objekt und hängt den Text an den angegebenen StringBuffer an (eine Methode mit StringBuilder gibt es nicht). Kann die Zeichenkette nicht mit format(…) nach den Regeln des Format-Objekts ausgegeben werden, löst die Methode eine IllegalArgumentException aus. Ist die Formatierungsanweisung falsch, so gibt format(…) das Unicode-Zeichen \uFFFD zurück.

  • Object parseObject(String source)
    Analysiert den Text von Anfang an.

  • abstract Object parseObject(String source, ParsePosition pos)
    Der Text wird ab der Stelle pos umgewandelt. Konnte parseObject(…) die Zeichenkette nicht zurückübersetzen, so folgt eine ParseException. parseObject(String, ParsePosition) verändert das ParsePosition-Objekt nicht und gibt die null-Referenz zurück.

  • Object clone()
    Gibt eine Kopie zurück.

Die Mehrzahl der Format-Unterklassen implementiert statische Fabrikmethoden der Art:

  • static XXXFormat getYYYInstance()
    Liefert ein Formatierungsobjekt mit den Formatierungsregeln für das voreingestellte Land.

  • static XXXFormat getYYYInstance(Locale l)
    Liefert ein Formatierungsobjekt mit den Formatierungsregeln für das angegebene Land. So erlauben es die Unterklassen von Format dem Benutzer auch, weitere Objekte zu erzeugen, die an die speziellen Sprachbesonderheiten der Länder angepasst sind.

 
Zum Seitenanfang

2.5.4Zahlen, Prozente und Währungen mit NumberFormat und DecimalFormat formatieren * Zur vorigen ÜberschriftZur nächsten Überschrift

NumberFormat widmet sich der Ausgabe von Zahlen. Dabei unterstützt die Klasse vier Typen von Ausgaben, für die es jeweils eine statische Fabrikmethode gibt.

abstract class java.text.NumberFormat
extends Format
  • static NumberFormat getNumberInstance()
    Liefert den einfachen Formatierer für Zahlen.

  • static NumberFormat getIntegerInstance()
    Liefert einen Formatierer, der den Nachkommateil abschneidet und rundet.

  • static NumberFormat getPercentInstance()
    Liefert einen Formatierer, der Fließkommazahlen über die format(…)-Methode im Bereich von 0 bis 1 annimmt und dann als Prozentzahl formatiert. Nachkommastellen werden abgeschnitten.

  • static NumberFormat getCurrencyInstance()
    Liefert einen Formatierer für Währungen, der ein Währungszeichen zur Ausgabe hinzufügt.

Die genannten vier statischen Methoden gibt es jeweils in der parameterlosen Variante und in der Variante mit einem Locale-Objekt, um etwa das Währungszeichen oder das Kommazeichen anzupassen.

Dezimalzahlformatierung mit DecimalFormat

DecimalFormat ist eine Unterklasse von NumberFormat und ermöglicht individuellere Anpassungen an die Ausgabe. Dem Konstruktor kann ein Formatierungs-String übergeben werden, sozusagen eine Vorlage, wie die Zahlen zu formatieren sind. Die Formatierung einer Zahl durch DecimalFormat erfolgt mit Rücksicht auf die aktuell eingestellte Sprache:

Listing 2.20DecimalFormatDemo.java, main()

double d = 12345.67890;
DecimalFormat df = new DecimalFormat( "###,##0.00" );
System.out.println( df.format( d ) ); // 12.345,68

Der Formatierungs-String kann eine Menge von Formatierungsanweisungen vertragen; im Beispiel kommen #, 0 und das Komma vor. Die beiden wichtigen Symbole sind jedoch 0 und #. Beide repräsentieren Ziffern. Der Unterschied tritt erst dann zu Tage, wenn weniger Zeichen zum Formatieren da sind, als im Formatierungs-String genannt werden.

Symbol

Bedeutung

0

Repräsentiert eine Ziffer – ist die Stelle nicht belegt, wird eine Null angezeigt.

#

Repräsentiert eine Ziffer – ist die Stelle nicht belegt, bleibt sie leer, damit führende Nullen und unnötige Nullen hinter dem Komma nicht angezeigt werden.

.

Dezimaltrenner, trennt Vor- und Nachkommastellen.

,

Gruppiert die Ziffern (eine Gruppe ist so groß wie der Abstand von
»,« zu ».«).

;

Trennzeichen; links davon steht das Muster für positive Zahlen, rechts davon das Muster für negative Zahlen.

-

das Standardzeichen für das Negativpräfix

%

Die Zahl wird mit 100 multipliziert und als Prozentwert ausgewiesen.

\u2030

Die Zahl wird mit 1.000 multipliziert und als Promillewert ausgezeichnet.

\u00A4

nationales Währungssymbol (€ für Deutschland)

\u00A4\u00A4

internationales Währungssymbol (EUR für Deutschland)

X

Alle anderen Zeichen – symbolisch X – können ganz normal benutzt werden.

'

Ausmaskieren von speziellen Symbolen im Präfix oder Suffix

Tabelle 2.13Formatierungsanweisungen für DecimalFormat

Hier sehen wir ein Beispiel für die Auswirkungen der Formatanweisungen auf einige Zahlen:

Format

Eingabezahl

Ergebnis

0000

12

0012

0000

12,5

0012

0000

1234567

1234567

##

12

12

##

12.3456

12

##

123456

123456

.00

12.3456

12,35

.00

.3456

,35

0.00

.789

0,79

#.000000

12.34

12,340000

,###

12345678.901

12.345.679

#.#;(#.#)

12345678.901

12345678,9

#.#;(#.#)

–12345678.901

(12345678,9)

,###.## \u00A4

12345.6789

12.345,68 €

,#00.00 \u00A4\u00A4

–12345678.9

–12.345.678,90 EUR

,#00.00 \u00A4\u00A4

0.1

00,10 EUR

Tabelle 2.14Beispiel für verschiedene Formatanweisungen

Währungen angeben und die Klasse Currency

Die NumberFormat-Klasse liefert mit getCurrencyInstance() ein Format-Objekt, das neben der Dezimalzahl auch noch ein Währungssymbol mit anzeigt. So liefert NumberFormat.getCurrencyInstance().format(12345.6789) dann 12.345,68 €, also automatisch mit einem Euro-Zeichen. Dass es ein Euro-Zeichen ist und kein Yen-Symbol, liegt einfach daran, dass Java standardmäßig das eingestellte Land »sieht« und daraus die Währung ableitet. Wenn wir explizit den Formatter mit einem Land initialisieren, etwa wie in

NumberFormat frmt1 = DecimalFormat.getCurrencyInstance( Locale.FRANCE );
System.out.println( frmt1.format( 12345.6789 ) ); // 12345,68 €

so ist die Währung automatisch Euro (denn Frankreich nutzt den Euro); schreiben wir DecimalFormat.getCurrencyInstance(Locale.JAPAN), ist sie Yen, und wir bekommen ¥12,346 (es gibt standardmäßig keine Nachkommastellen beim Yen). Locale-Objekte repräsentieren immer eine Sprachregion.

DecimalFormat bzw. schon die Oberklasse NumberFormat ermöglicht die explizite Angabe der Währung. In der Java-Bibliothek wird sie durch die Klasse java.util.Currency repräsentiert. NumberFormat liefert mit getCurrency() die eingestellte Currency, die zur Formatierung verwendet wird, und setCurrency() setzt sie neu. Das löst Szenarios, in denen etwa ein Euro-Zeichen die Währung darstellt, aber die Zahlenformatierung englisch ist, wie die folgenden Zeilen zeigen:

NumberFormat frmt = DecimalFormat.getCurrencyInstance( Locale.ENGLISH );
frmt.setCurrency( Currency.getInstance( "EUR" ) );
System.out.println( frmt.format( 12345.6789 ) ); // EUR12,345.68

Die Currency-Klasse bietet drei statische Methoden, die Currency-Objekte liefern. Da ist zum einen getAvailableCurrencies(), was ein Set<Currency> liefert, und zum anderen gibt es die beiden Fabrikfunktionen getInstance(Locale locale) und getInstance(String currencyCode). Currency-Objekte besitzen eine ganze Reihe von Objektfunktionen, die etwa den ISO-4217-Währungscode liefern oder den ausgeschriebenen Währungsnamen (und das auch noch in verschiedenen Sprachen, wenn gewünscht).

Folgendes Programm geht über alle Währungen und gibt die zentralen Informationen aus:

for ( Currency currency : Currency.getAvailableCurrencies() ) {
System.out.printf( "%s, %s, %s (%s)%n",
currency.getCurrencyCode(),
currency.getSymbol(),
currency.getDisplayName(),
currency.getDisplayName(Locale.ENGLISH) );
}

Wir bekommen dann mehr als 200 Ausgaben, und die Ausgabe beginnt mit:

EGP, EGP, Ägyptisches Pfund (Egyptian Pound)
IQD, IQD, Irak Dinar (Iraqi Dinar)
GHS, GHS, Ghana Cedi (Ghana Cedi)
AFN, AFN, Afghani (Afghani)
MUR, MUR, Mauritius Rupie (Mauritius Rupee)
SGD, SGD, Singapur Dollar (Singapore Dollar)
 
Zum Seitenanfang

2.5.5MessageFormat und Pluralbildung mit ChoiceFormat Zur vorigen ÜberschriftZur nächsten Überschrift

MessageFormat ist eine besondere Unterklasse von Format, die für die Formulierung von Texten gedacht ist. Insbesondere bei internationalisierten Ausgaben kommt die Klasse zum Einsatz. Die Klasse ist in etwa mit den Formatierungen über printf(…) vergleichbar, nur werden bei MessageFormat die Platzhalter immer per Index in geschweiften Klammern angesprochen.

[zB]Beispiel

Formuliere einen Nachrichten-String mit drei Feldern:

int soldCars = 10;
double sum = 1234534534;
String s = MessageFormat.format( "{0} Auto(s) verkauft am {1,date} zum "+
"Gesamtpreis von {2,number,currency}.",
soldCars, new Date(), sum );
System.out.println( s );

Die Ausgabe ist:
»10 Auto(s) verkauft am 01.07.2011 zum Gesamtpreis von 1.234.534.534,00 €.«
Sie ist automatisch lokalisiert, die Sprache lässt sich jedoch wieder als Locale-Objekt übergeben.

ChoiceFormat

Eine besondere Möglichkeit ist die Verbindung von MessageFormat und ChoiceFormat, um das Problem zu lösen, das unser Beispiel im Fall von verkauften Autos mit »Auto(s)« löst. Im Deutschen ist die Pluralbildung anspruchsvoll, da es »0 Autos, 1 Auto, 2 Autos, 3 Autos« usw. heißt, aber nur »0 Koffer, 1 Koffer, 2 Koffer, …«. Das in Software zu modellieren ist nicht ganz einfach, aber mit ChoiceFormat lässt es sich lösen. Dem Konstruktor werden zum Generieren der Ausgabe zwei Felder mitgegeben: Ein Limit-Array kodiert Bereiche, und ein zweites Feld enthält die zugeordneten Elemente für den Bereich.

[zB]Beispiel

Löse das Problem mit »0 Autos, 1 Auto, 2 Autos« usw.:

MessageFormat formatter = new MessageFormat( "Du hast {0} {1} verkauft." );
double[] limits = { 0., 1., 2. };
String[] formats = { "Autos", "Auto", "Autos" };
ChoiceFormat choices = new ChoiceFormat( limits, formats );
formatter.setFormatByArgumentIndex( 1, choices );
int size = 4;
Object[] params = { size, size };
System.out.println( formatter.format( params ) ); // Du hast 4 Autos verkauft.

Das Feld {0., 1., 2.} interpretiert sich so: Liegt der Wert zwischen größer gleich 0 und echt kleiner 1 (also bei Ganzzahlen ist er effektiv 0), wird das erste Element des Feldes {"Autos", "Auto", "Autos"}, also »Autos«, gewählt. Liegt es zwischen größer gleich 1 und echt kleiner 2, dann ist es das »Auto«. Alles, was echt größer 2 ist, wird auf »Autos« abgebildet. Für die 2 im Feld ist Math.nextUp(1.) eine Alternative, und wenn auf »Komma-Autos« gewechselt wird, ist es gleich korrekt, denn es heißt zwar »1 Auto« aber »1,5 Autos«. (Genau genommen sind es sogar »1,0 Autos«, wodurch die ganze Pluralbildung wegfällt.)

Die API-Dokumentation der Klasse ChoiceFormat gibt weitere Beispiele und zeigt insbesondere, wie sich die Bereiche auch in den Strings selbst kodieren lassen, was für externe Übersetzungsdateien optimal ist.

 


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
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.

 
Nutzungsbestimmungen | Datenschutz | Impressum

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

Cookie-Einstellungen ändern