Intelligente Zeichenkonvertierung?

Hallo Leute

Ich habe in einem Java-Programm Text, der Zeichen enthält, die nicht im ISO-8859-1-Zeichensatz enthalten sind. Diesen Text möchte ich nun ISO-8859-1-codiert in eine Textdatei schreiben. Dabei sollen aber diese Sonderzeichen durch ein möglichst ähnliches Zeichen ersetzt werden, um die Lesbarkeit des Textes halbwegs zu erhalten.

In etwa also die Funktionalität, wie sie z.b. das notepad.exe unter Windows XP liefert: Habe ich eine UTF-8 Datei die u.a. ein c mit Hatschek beinhaltet und ich speichere diese Datei mit Speichern-Unter als ANSI (also ISO-8859-1) ab, wird das Hatschek-c durch ein normales c ersetzt.

Im Java habe ich bisher nur was gefunden, dass diese Sonderzeichen durch ein Fragezeichen ersetzt oder komplett weglässt.

Jetzt kann ich natürlich selber eine Ersetzungstabelle basteln und allen Zeichen ein halbwegs ähnliches aus dem ISO-8859-1 zuordnen. Aber das ist mühsam. Natürlich gibt es auch Zeichen ohne einer sinnvollen Entsprechung - im Prinzip alles, was nicht auf lateinischen Buchstaben basiert. Aber die kommen in meinen Texten praktisch nie vor.

Gibt es da fix-fertigen Standardcode den ich weiterverwenden kann?

Google-Suche liefert leider nichts brauchbares…

lg
Erwin

Hallo,

Gibt es da fix-fertigen Standardcode den ich weiterverwenden
kann?

was fertiges kenne ich nicht, aber es gibt ab Java 7 die Methode Character.getName(), evtl. genügt der folgende Quick ‚n‘ Dirty Ansatz ja bereits deinen Anforderungen, sollte eigentlich für alle Zeichen mit Lateinischer Basis funktionieren:

public class CharacterTest
{
 public static void main(String[] args)
 {
 // String latin1 = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏD…ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßE…àáâãäåæçèéêëìíîïF…ðñòóôõö÷øùúûüýþÿ";
 String latin2 = "čéîČĚÎ";

 for(char c : latin2.toCharArray())
 {
 String name = Character.getName(c);
 System.out.println("Char " + c + " is " + name);
 System.out.println(" replaced: " + replace(name));
 }
 System.exit(0); 
 }

 public static char replace(String name)
 {
 boolean small = name.matches(".\*SMALL.LETTER.\*");
 String base = name.replaceFirst(".\*LETTER ([A-Z]).\*", "$1");
 if(small)
 {
 base = base.toLowerCase();
 }
 return base.charAt(0);
 }
}

Ausgabe:

Char č is LATIN SMALL LETTER C WITH CARON
 replaced: c
Char é is LATIN SMALL LETTER E WITH ACUTE
 replaced: e
Char î is LATIN SMALL LETTER I WITH CIRCUMFLEX
 replaced: i
Char Č is LATIN CAPITAL LETTER C WITH CARON
 replaced: C
Char Ě is LATIN CAPITAL LETTER E WITH CARON
 replaced: E
Char Î is LATIN CAPITAL LETTER I WITH CIRCUMFLEX
 replaced: I

Gruß
Heavy

Alternative mit RegEx
Hallo,

eben noch gefunden:

http://stackoverflow.com/questions/1008802/convertin…

HTH
Heavy

danke!!!

ist halt die hohe kunst des googlens: die suchbegriffe in der richtigen reihenfolge und schon klappts…

deinen dirty hack finde ich auch recht interessant - muss da mal den sourcecode der jeweiligen klassen durchstöbern - vielleicht gibt es da sogar noch was eleganteres.

auf jeden fall vielen dank für die hilfe - hilft mir viel weiter.

lg
erwin

Bei positivem Feedback antwortet man doch gerne :smile:

Nachdem ich deine Ursprungsfrage nochmal gelesen habe glaube ich aber meine Ansätze treffen das noch nicht ganz. Du möchtest ja nur Zeichen ersetzen die nicht in Latin1 enthalten sind, das ist bei meinen Beispielen nicht der Fall, die entfernen alle Accents etc. auch solche die in Latin1 vorkommen. Man sollte daher noch prüfen aus welchem Unicode-Block das Zeichen stammt und nur ersetzen wenn nicht Latin1:

String block = String.valueOf(Character.UnicodeBlock.of(c));
char replaced = block.equals("LATIN\_1\_SUPPLEMENT") 
 ? c 
 : replace(name);
System.out.println(" replaced: " + replaced);

Gruß
Heavy

1 Like

hallo

deine idee ist sehr gut - schießt aber für meinen speziellen fall übers ziel hinaus.

ich habe nämlich einige details verschwiegen um die frage nicht zu lang werden zu lassen. de facto konvertiere ich auf 7-bit-ascii und nicht auf latin1. da fliegen auch umlaute und scharfe-s weg. nur soll das ergebnis trotzdem so lesbar wie möglich sein. ein erster filter ersetzt bereits ein „ä“ in „ae“ und „ß“ in „ss“ usw. funktioniert für deutsche sprache mit wenigen handgriffen und deckt über 99% der fälle ab. sobald ich aber z.b. mit ausländischen namen zu tun bekomme, gibt es probleme. da ist der ansatz mit der regular expression im anschluss an den ersten filter genau der richtige. hier ist es eben absicht, alles wegzufiltern, was nicht nach 7-bit-ascii aussieht.

danke aber trotzdem für den input - lerne immer wieder gerne dazu.

lg
erwin

Da hoffe ich mal, dass Dir kein Esperanto-Text in die Finger fällt. Z.B. bedeutet das Esperanto-Wort ŝerci scherzen, während serĉi suchen bedeutet. Beide Zeichen, ŝ und ĉ sind nicht im Ascii-Code, noch nicht einmal in Latin-1, weshalb im E-Mail-Verkehr oft eine Ersatzdarstellung gewählt wird: sherci bzw. serchi.
Gruß Pit.

hallo

mir ist klar, dass diese vorgehensweise bei bestimmten sprachen in etwa den effekt hat, als wenn man in einem deutschen text 90% der buchstaben durch willkürlich gewählte andere austauscht.

für meinen einsatzzweck ist diese vorgehensweise aber denoch angebracht. ich rechne hauptsächlich bei namen osteuropäischen ursprungs mit problematischen zeichen - da kann ich kleinere verwirrungen schon verschmerzen.

lg
erwin

Hallo @Heavy,

ich brauchte genau das für eine Konvertierung für Flugteilnehmer. Danke dafür!

Gruß Udo