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 Sprachbeschreibung
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Eigene Klassen schreiben
6 Exceptions
7 Generics<T>
8 Äußere.innere Klassen
9 Besondere Klassen der Java SE
10 Architektur, Design und angewandte Objektorientierung
11 Die Klassenbibliothek
12 Bits und Bytes und Mathematisches
13 Datenstrukturen und Algorithmen
14 Threads und nebenläufige Programmierung
15 Raum und Zeit
16 Dateien, Verzeichnisse und Dateizugriffe
17 Datenströme
18 Die eXtensible Markup Language (XML)
19 Grafische Oberflächen mit Swing
20 Grafikprogrammierung
21 Netzwerkprogrammierung
22 Verteilte Programmierung mit RMI
23 JavaServer Pages und Servlets
24 Datenbankmanagement mit JDBC
25 Reflection und Annotationen
26 Dienstprogramme für die Java-Umgebung
A Die Begleit-DVD
Stichwort
Ihre Meinung?

Spacer
 <<   zurück
Java ist auch eine Insel von Christian Ullenboom
Das umfassende Handbuch
Buch: Java ist auch eine Insel

Java ist auch eine Insel
geb., mit DVD
1482 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1506-0
Pfeil 4 Der Umgang mit Zeichenketten
  Pfeil 4.1 Einzelne Zeichen behandeln
    Pfeil 4.1.1 Von ASCII über ISO-8859-1 zu Unicode
    Pfeil 4.1.2 Die Character-Klasse
  Pfeil 4.2 Strings und deren Anwendung
    Pfeil 4.2.1 String-Literale als String-Objekte für konstante Zeichenketten
    Pfeil 4.2.2 String-Länge und Test auf Leerstring
    Pfeil 4.2.3 Nach enthaltenen Zeichen und Zeichenfolgen suchen
    Pfeil 4.2.4 Gut, dass wir verglichen haben
    Pfeil 4.2.5 Phonetische Vergleiche
    Pfeil 4.2.6 String-Teile extrahieren
    Pfeil 4.2.7 Strings anhängen, Groß-/Kleinschreibung und Leerraum
    Pfeil 4.2.8 Suchen und ersetzen
    Pfeil 4.2.9 String-Objekte mit Konstruktoren neu anlegen *
  Pfeil 4.3 Konvertieren zwischen Primitiven und Strings
    Pfeil 4.3.1 Unterschiedliche Typen in String-Repräsentationen konvertieren
    Pfeil 4.3.2 Stringinhalt in primitiven Wert konvertieren
    Pfeil 4.3.3 Unterschiedliche Ausgabeformate (Binär, Hex, Oktal) *
  Pfeil 4.4 Veränderbare Zeichenketten mit StringBuilder und StringBuffer
    Pfeil 4.4.1 Anlegen von StringBuilder/StringBuffer-Objekten
    Pfeil 4.4.2 StringBuilder/StringBuffer in andere Zeichenkettenformate konvertieren
    Pfeil 4.4.3 Daten anhängen
    Pfeil 4.4.4 Zeichen(folgen) setzen, erfragen, löschen und umdrehen
    Pfeil 4.4.5 Länge und Kapazität eines StringBuilder/StringBuffer-Objekts *
    Pfeil 4.4.6 Vergleichen von String mit StringBuilder und StringBuffer
    Pfeil 4.4.7 »hashCode()« bei StringBuilder/StringBuffer *
  Pfeil 4.5 CharSequence als Basistyp *
  Pfeil 4.6 Sprachabhängiges Vergleichen und Normalisierung *
    Pfeil 4.6.1 Die Klasse »Collator«
    Pfeil 4.6.2 Effiziente interne Speicherung für die Sortierung
    Pfeil 4.6.3 Normalisierung
  Pfeil 4.7 Reguläre Ausdrücke
    Pfeil 4.7.1 Arbeiten mit der Fassade: String#matches()
    Pfeil 4.7.2 Die Klassen Pattern und Matcher
    Pfeil 4.7.3 Finden und nicht matchen
    Pfeil 4.7.4 Gierige und nicht gierige Operatoren *
    Pfeil 4.7.5 Mit MatchResult alle Ergebnisse einsammeln *
    Pfeil 4.7.6 Suchen und Ersetzen mit Mustern
  Pfeil 4.8 Zerlegen von Zeichenketten
    Pfeil 4.8.1 Splitten von Zeichenketten mit »split()«
    Pfeil 4.8.2 Die Klasse Scanner
    Pfeil 4.8.3 Die Klasse StringTokenizer *
    Pfeil 4.8.4 BreakIterator als Zeichen-, Wort-, Zeilen- und Satztrenner *
  Pfeil 4.9 Zeichenkodierungen, XML/HTML-Entitys, Base64 *
    Pfeil 4.9.1 Unicode und 8-Bit-Abbildungen
    Pfeil 4.9.2 Konvertieren mit »OutputStreamWriter«-Klassen
    Pfeil 4.9.3 Das Paket »java.nio.charset«
    Pfeil 4.9.4 XML/HTML-Entitys ausmaskieren
    Pfeil 4.9.5 Base64-Kodierung
  Pfeil 4.10 Ausgaben formatieren
    Pfeil 4.10.1 Formatieren und Ausgeben mit »format()«
    Pfeil 4.10.2 Die Formatter-Klasse *
    Pfeil 4.10.3 Formatieren mit Masken *
    Pfeil 4.10.4 Format-Klassen
    Pfeil 4.10.5 Zahlen, Prozente und Währungen mit »NumberFormat« und »DecimalFormat« formatieren *
  Pfeil 4.11 Zum Weiterlesen

»Ohne Unterschied macht Gleichheit keinen Spaß.« – Dieter Hildebrandt (*1927)

4 Der Umgang mit Zeichenketten


Rheinwerk Computing - Zum Seitenanfang

4.1 Einzelne Zeichen behandeln  Zur nächsten ÜberschriftZur vorigen Überschrift


Rheinwerk Computing - Zum Seitenanfang

4.1.1 Von ASCII über ISO-8859-1 zu Unicode  Zur nächsten ÜberschriftZur vorigen Überschrift

Die Übertragung von Daten spielte in der IT schon immer eine zentrale Rolle. Daher haben sich unterschiedliche Standards herausgebildet.

ASCII

Um Dokumente austauschen zu können, führte die American Standards Association im Jahr 1963 eine 7-Bit-Kodierung ein, die ASCII (von American Standard Code for Information Interchange) genannt wird. ASCII gibt jedem der 128 Zeichen (mehr Zeichen passen in 7 Bit nicht hinein) eine eindeutige Position, die Codepoint (Codeposition) genannt wird. Es gibt 94 druckbare Zeichen (Buchstaben, Ziffern, Interpunktionszeichen), 33 nicht druckbare Kontrollzeichen (etwa den Tabulator und viele andere Zeichen, die bei Fernschreibern nützlich waren, aber heute uninteressant sind), und das Leerzeichen, das nicht als Kontrollzeichen gezählt wird. Am Anfang des ASCII-Alphabets stehen an den Positionen 0–31 Kontrollzeichen, an Stelle 32 folgt das Leerzeichen und anschließend alle druckbaren Zeichen. An der letzten Position, 127, wird ASCII von einem Kontrollzeichen abgeschlossen.

Die folgende Tabelle stammt aus dem Originalstandard von 1968 und gibt einen Überblick über die Position der Zeichen.

ISO/IEC 8859-1

An dem ASCII-Standard gab es zwischendurch Aktualisierungen, sodass einige Kontrollzeichen entfernt wurden, doch in 7 Bit konnten nie alle länderspezifischen Zeichen untergebracht werden. Wir in Deutschland haben Umlaute, die Russen haben ein kyrillisches Alphabet, die Griechen Alpha und Beta und so weiter. Die Lösung war, statt einer 7-Bit-Kodierung, die 128 Zeichen unterbringen kann, einfach 8 Bit zu nehmen, womit 265 Zeichen kodiert werden können. Da in weiten Teilen der Welt das lateinische Alphabet genutzt wird, sollte diese Kodierung natürlich alle die Buchstaben zusammen mit einem Großteil aller diakritischen Zeichen (das sind etwa ü, á, à, ó, â, Å, Æ) umfassen. So setzte sich ein Standardisierungsgremium zusammen und schuf 1985 den ISO/IEC 8859-1-Standard, der 191 Zeichen beschreibt. Die Zeichen aus dem ASCII-Alphabet behalten ihre Positionen. Wegen der lateinischen Buchstaben hat sich die informelle Bezeichnung Latin-1 als Alternative zu ISO/IEC 8859-1 etabliert.

Alle Zeichen aus ISO/IEC 8859-1 sind druckbar, sodass alle Kontrollzeichen – etwa der Tabulator oder das Zeilenumbruchzeichen – nicht dazu gehören. Von den 256 möglichen Positionen bleiben 65 Stellen frei. Das sind die Stellen 0 bis 31 sowie 127 von den ASCII-Kontrollzeichen und zusätzlich 128 bis 159.

ISO 8859-1

Da es kaum sinnvoll ist, den Platz zu vergeuden, gibt es eine Erweiterung des ISO/IEC 8859-1-Standards, die unter dem Namen ISO 8859-1 (also ohne IEC) geläufig ist. ISO 8859-1 enthält alle Zeichen aus ISO/IEC 8859-1 sowie die Kontrollzeichen aus dem ASCII-Standard an den Positionen 0–31 und 127. Somit steckt ASCII vollständig in ISO 8858-1, aber nur die druckbaren ASCII-Zeichen sind in ISO/IEC 8859-1. Auch die Stellen 128 bis 159 sind in ISO 8858-1 definiert, wobei es alles recht unbekannte Kontrollzeichen (wie Padding, Start einer Selektion, kein Umbruch) sind.

Windows-1252 *

Weil die Zeichen an der Stelle 128 bis 159 uninteressante Kontrollzeichen sind, belegt Windows sie mit Buchstaben und Interpunktionszeichen und nennt die Kodierung Windows-1252. An Stelle 128 liegt etwa das €-Zeichen, an 153 das ™-Symbol. Diese Neubelegung der Plätze 128 bis 159 hat sich mittlerweile auch in der Nicht-Windows-Welt etabliert, sodass das, was im Web als ISO-8859-1 deklariert ist, heute die Symbole aus den Codepoints 128 bis 159 enthalten kann und von Browsern so dargestellt wird.

Unicode

Obwohl Latin-1 für die »großen« Sprachen alle Zeichen mitbrachte, fehlen Details, wie Ő, ő, Ű, ű für das Ungarische, das komplette griechische Alphabet, die kyrillischen Buchstaben, chinesische und japanische Zeichen, mathematische Zeichen und vieles mehr. Um das Problem zu lösen, hat sich das Unicode-Konsortium gebildet, um jedes Zeichen der Welt zu kodieren und ihm einen eindeutigen Codepoint zu geben. Unicode enthält alle Zeichen aus ISO 8859-1, was die Konvertierung von Dokumenten vereinfacht. So behält zum Beispiel »A« den Codepoint 65 von ISO 8859-1, den der Buchstabe wiederum von ASCII erbt. Die letzte Version des Unicode-Standards ist 5.1. Sie beschreibt ca. 107.000 Zeichen.

Wegen der vielen Zeichen ist es unpraktisch, diese dezimal anzugeben, sodass sich die hexadezimale Angabe durchgesetzt hat. Der Unicode-Standard nutzt das Präfix »U+« gefolgt von Hexadezimalzahlen. Der Buchstabe »A« ist dann U+0041.

Unicode-Zeichenkodierung

Da es im Unicode-Standard 5.1 um die 107.000 Zeichen gibt, werden zur Kodierung eines Zeichens 4 Byte beziehungsweise 32 Bit verwendet. Ein Dokument, das Unicode 5.1-Zeichen enthält, wird dann einen Speicherbedarf von 4 × »Anzahl der Zeichen« besitzen. Wenn die Zeichen auf diese Weise kodiert werden, sprechen wie von einer UTF-32-Kodierung.

Für die meisten Texte ist UTF-32 reine Verschwendung, denn besteht der Text aus nur einfachen ASCII-Zeichen, sind 3 Byte gleich 0. Gesucht ist eine Kodierung, die die allermeisten Texte kompakt kodieren kann, aber dennoch jedes der Unicode-5.1-Zeichen zulässt. Zwei Kodierungen sind üblich: UTF-8 und UTF-16. UTF-8 kodiert ein Zeichen entweder in 1, 2, 3 oder 4 Byte, UTF-16 in 2 Byte oder 4 Byte. Das folgende Beispiel [http://java.sun.com/developer/technicalArticles/Intl/Supplementary/ ] zeigt die Kodierung für die Buchstaben »A« und »ß«, für das chinesische Zeichen für Osten und für ein Zeichen aus dem Deseret, einem phonetischen Alphabet.


Tabelle 4.1  Zeichenkodierung in den verschiedenen Unicode-Versionen

Glyph A ß 𐐀

Unicode Codepoint

U+0041

U+00DF

U+6771

U+10400

UTF-32

00000041

000000DF

00006771

00 01 04 00

UTF-16

00 41

00 DF

6771

D801 DC00

UTF-8

41

C3 9F

E6 9D B1

F0 90 90 80


Werden Texte ausgetauscht, sind diese üblicherweise UTF-8 kodiert. Bei Webseiten ist das ein guter Standard. UTF-16 ist für Dokumente seltener, wird aber häufiger als interne Textrepräsentation genutzt. So verwenden zum Beispiel die JVM und die .NET-Laufzeitumgebung intern UTF-16.

Standardmäßig ist ein char 2 Byte groß. Das heißt aber auch, dass ein Zeichen, das größer als 65.536 ist, irgendwie anders kodiert werden muss. Dazu muss ein »großes« Unicode-Zeichen durch zwei char zusammengesetzt werden. Dieses Pärchen wird Surrogate-Paar genannt. Unter Java 5 gab es an den String-Klassen einige Änderungen, sodass etwa eine Methode, die nach einem Zeichen sucht, nun nicht nur mit einem char parametrisiert ist, sondern auch mit int, und damit das Surrogate-Paar übergeben werden kann. In diesem Buch spielt das aber keine große Rolle, da diese Unicode-Zeichen nur für eine ganz kleine Gruppe von Interessenten wichtig sind.


Entwicklerfrust Die Abbildung eines Zeichens auf eine Position übernimmt eine Tabelle, die sich Codepage nennt. Nur gibt es unterschiedliche Abbildungen der Zeichen auf Positionen, und das führt zu Problemen beim Dokumentenaustausch. Denn wenn eine Codepage die Tilde »~« auf Position 161 setzt und eine andere Codepage das »ß« auch auf Position 161 anordnet, dann führt das zwangsläufig zu Ärgernissen. Daher muss beim Austausch von Textdokumenten immer ein Hinweis mitgegeben werden, in welchem Format die Texte vorliegen. Leider unterstützen die Betriebssysteme aber solche Meta-Angaben nicht, und so werden sie etwa in XML- oder HTML-Dokumenten in den Text selbst geschrieben. Bei Unicode-UTF-16-Dokumenten gibt es eine andere Konvention, sodass sie mit den Hexwert 0xFEFF beginnen – das wird BOM (byte order mark) genannt und dient gleichzeitig als Indikator für die Byte-Reihenfolge.



Rheinwerk Computing - Zum Seitenanfang

4.1.2 Die Character-Klasse  topZur vorigen Überschrift

Die im Kernpaket java.lang angesiedelte Klasse Character bietet eine große Anzahl statischer Methoden, die im Umgang mit einzelnen Zeichen interessant sind. Dazu gehören Methoden zum Testen, etwa ob ein Zeichen eine Ziffer, ein Buchstabe oder ein Sonderzeichen ist. Ihnen ist gemeinsam, dass sie alle mit der Vorsilbe is beginnen und ein boolean liefern. Dazu gesellen sich Methoden zum Konvertieren, etwa in Groß-/Kleinschreibung.


Beispiel für isDigit() und isLetter():

Listing 4.1  CharacterDemo.java, main()

System.out.println( Character.isDigit( '0' ) );      // true
System.out.println( Character.isDigit( '-' ) );      // false
System.out.println( Character.isLetter( 'ß' ) );     // true
System.out.println( Character.isLetter( '0' ) );     // false
System.out.println( Character.isWhitespace( ' ' ) ); // true
System.out.println( Character.isWhitespace( '-' ) ); // false

Alle diese Methoden »wissen« über die Eigenschaften der einzelnen Unicode-Zeichen Bescheid. Und 0 bleibt ja immer eine Null, egal ob das Programm in Deutschland oder in der Mongolei ausgeführt wird, denn der Codepoint jedes Unicode-Zeichens ist immer der gleiche.

Oftmals finden die Testfunktionen Anwendung beim Ablaufen einer Zeichenkette.


Beispiel Eine Zeichenkette soll in Großbuchstaben umgesetzt beziehungsweise Weißraum soll zu einem Unterstrich werden:

Listing 4.2  UppercaseWriter.java, main()

char[] chars = { 'M', 'e', ' ', '2' };
for ( char c : chars
  if ( Character.isWhitespace(
    System.out.print( '_' );
  else
    System.out.print( Character.toUpperCase( c ) );


final class java.lang.Character
implements Serializable, Comparable<Character>

  • static boolean isDigit( char ch ) Handelt es sich um eine Ziffer zwischen 0 und 9?
  • static boolean isLetter( char ch ) Handelt es sich um einen Buchstaben?
  • static boolean isLetterOrDigit( char ch ) Handelt es sich um ein alphanumerisches Zeichen?
  • static boolean isLowerCase( char ch ), boolean isUpperCase( char ch ) Ist es ein Klein- oder ein Großbuchstabe?
  • static boolean isWhiteSpace( char ch ) Ist es ein Leerzeichen, Zeilenvorschub, Return oder Tabulator, also ein so genannter Weißraum (engl. white space) [Es wird Weißraum genannt, weil das ausgegebene Zeichen den Raum in der Regel weiß lässt, aber die Position der Ausgabe dennoch fortschreitet. ] , auch Leerraum genannt?
  • static boolean isJavaIdentifierStart( char ch ) Ist es ein Java-Buchstabe, mit dem Bezeichner beginnen dürfen?
  • static boolean isJavaIdentifierPart( char ch ) Ist es ein Java-Buchstabe oder eine Ziffer, der beziehungsweise die in der Mitte eines Bezeichners vorkommen darf?
  • static boolean isTitleCase( char ch ) Sind es spezielle Zwei-Buchstaben-Paare mit gemischter Groß- und Kleinschreibung? Dies kommt etwa im Spanischen vor, wo »lj« für einen einzigen Buchstaben steht. In Überschriften erscheint dieses Paar als »Lj« und wird von dieser Methode als Sonderfall erkannt. Unter http://www.unicode.org/reports/tr21/tr21-5.html schreibt der Unicode-Standard die Konvertierung vor.
  • static char toUpperCase( char ch ), static char toLowerCase( char ch ) Die statischen Methoden toUpperCase() und toLowerCase() liefern den passenden Groß- beziehungsweise Kleinbuchstaben zurück.

Hinweis Die Methoden toUpperCase() und toLowerCase() gibt es zweimal: Einmal als statische Methoden bei Character – dann nehmen sie genau ein char als Argument – und einmal als Objektmethoden auf String-Exemplaren. Vorsicht ist bei Character.toUpperCase('ß') geboten, denn das Ergebnis ist »ß«, anders als bei der String-Methode toUpperCase("ß"), die das Ergebnis »SS« liefert; einen String, der um eins verlängert ist.


Die Character-Klasse besitzt ebenso eine Umwandlungsmethode für Ziffern bezüglich einer beliebigen Basis:


final class java.lang.Character
implements Serializable, Comparable<Character>

  • static int digit( char ch, int radix ) Liefert den numerischen Wert, den das Zeichen ch unter der Basis radix besitzt. Beispielsweise ist Character.digit('f', 16) gleich 15. Erlaubt ist jedes Zahlensystem mit einer Basis zwischen Character.MIN_RADIX (2) und Character.MAX_RADIX (36). Ist keine Umwandlung möglich, beträgt der Rückgabewert –1.
  • static char forDigit( int digit, int radix ) Konvertiert einen numerischen Wert in ein Zeichen. Beispielsweise ist Character.for Digit(6, 8) gleich »6« und Character.forDigit(12, 16) ist »c«.

Es ist bedauerlich, dass der Radix immer mit angegeben werden muss, obwohl er in der Regel immer 10 ist. Eine überladene statische Methode wäre hier angebracht.


Beispiel Steht in einem Zeichen c zum Beispiel '3' und soll aus diesem die Ganzzahl 3 werden, so besteht die traditionelle Art darin, eine '0' abzuziehen. Die ASCII-Null '0' hat den char-Wert 48, '1' dann 49, bis '9' schließlich 57 erreicht. So ist logischerweise '3' – '0' = 51 – 48 = 3.) Die digit()-Methode ist dazu eine Alternative. Wir nutzen sie in einem kleinen Beispiel, um eine Zeichenkette mit Ziffern schließlich zu einer Ganzzahl zu konvertieren.

Listing 4.3  CharacerDigitDemo.java, main()

char[] chars = { '3', '4', '0' };
int result = 0;
for ( char c : chars )
{
  result = result * 10 + Character.digit( c, 10 );
  System.out.println( result );
}

Die Ausgabe ist 3, 34 und 340.




Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
 <<   zurück
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Java ist auch eine Insel






 Java ist auch
 eine Insel


Zum Katalog: Java SE Bibliotheken






 Java SE Bibliotheken


Zum Katalog: Professionell entwickeln mit Java EE 7






 Professionell
 entwickeln mit
 Java EE 7


Zum Katalog: Einstieg in Eclipse






 Einstieg in
 Eclipse


Zum Katalog: Einstieg in Java






 Einstieg in
 Java


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2011
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