# Frage zu Umlauten ä, ü, ö, ß / Ausgeben eines Arrays



## Ecky (28. Jun 2004)

Hallo!
Ich habe nochmal 2 Fragen.

1.)
Ich habe WindowsXP und möchte gern über Dosaufforderung ein "ü" dargestellt haben.
Irgendwie funktioniert das nicht. Ein ä und ß klappt.
Ich habe ein Programm, da sind die Dos-Characters gleich aufgelistet.
Bei WinME funktioniert es ja auch,, aber bei XP nicht.
In der Zeichentabelle von XP hab ich für "ü" als Unicode=u00FC und als tastenkombination 0252.
Wenn ich das aber in Java so eingebe und kompiliere, kommen andere Zeichen.

2.)
Ich habe eine Klasse programmiert, die automatsich ein Array in der Größe erstellt, wie man über die Dos-Eingabeaufforderung eingibt.
z.B. java klasse test1.txt test2.txt dateizusammen.txt

Jetzt möchte ich über die Doseingabeaufforderung ausgeben:
"test1.txt, test2.txt wurden in die dateizusammen.txt hinzugefügt!"

Dabei sollen die Dateinamen bei der System.out.println() Methode, automatisch den Namen entsprechen, die als Argument der Klasse übergeben
wurden sind.
Das ist ja eigentlich kein Problem,,, aber in dem Array befinden sich z.B. in diesem Fall 3 Argumente. (test1.txt, test2.txt und dateizusammen.txt)
Aber ausgegeben werden, sollen nur die beiden ersten Argumente und das dritte dann extra.

z.B.:
mein Array heißt "dateien" und beinhaltet 3 Argumente.

Dann könnt ich, wenn ich alle 3 aufeinmal ausgeben möchte schreiben:
System.out.println(Arrays.asList(argumente));

Aber ich möchte gern haben, dass automatisch! nur die beiden ersten Argumente ausgegeben werden.
Und wenn das Array aber z.B. 10 Argumente besitzt, sollen nur die ersten 9 ausgegeben werden.

Gibt es dafür, ohne viel mit Schleifen etc. zu arbeiten, eine einfache Möglichkeit?
Habt jemand verstanden, was ich möchte?
Ich habe die Klasse um besseren Verständnis mal mit angefügt.


Wenn es nicht anders geht und ich mit einer Schleife arbeiten muss, wie mach ich das,, dass dem Array Argumente hinzugefügt werden, ohne das die, die es schon beinhaltet, gelöscht werden?



```
// diese Klasse wird von einer anderen aufgerufen und erhält von dort auch die Argumente

import java.io.*;
import java.util.Arrays;


public class DateiZusammen {


	private String argumente[];
	private int anzArgumente;



    public DateiZusammen (String argumente[]) {
		this.argumente = argumente;
		anzArgumente = argumente.length;
	}

    public void appendFiles() {
      try {
          for (int i=0; i<anzArgumente-1; i++) {  //die Schleife läuft so oft wie Argumente übergeben wurden -1
            BufferedReader lesen = new BufferedReader(new FileReader(argumente[i]));
            BufferedWriter schreiben = new BufferedWriter(new FileWriter(argumente[anzArgumente-1],true));

            String uebertragen;
            while ((uebertragen = lesen.readLine()) !=null)
              schreiben.write(uebertragen);
              schreiben.write(" ");
              lesen.close();
              schreiben.close();
          }
      }

      catch (Exception e) {
          e.printStackTrace();
	  }


	  System.out.println(Arrays.asList(argumente)+ "wurden in " +argumente[anzArgumente-1]+ "zusammengef\u00FCgt.");
	  //hier ist das "ü"Problem und dann möcht ich,dass das letzte Array-Argument nicht ausgegeben wird.
    }
}
```


----------



## Beni (28. Jun 2004)

> System.out.println(Arrays.asList(argumente));


Du kennst doch den Begriff, "overkill"?
Eine Liste herstellen, nur um was auszudrucken, also ehrlich  :noe: 

Das herstellen eines Strings kann man hervorragend in eine Methode schreiben (ohne es getestet zu haben):

```
public static String list( String[] array, int begin, int end ){
  StringBuffer buffer = new StringBuffer();
  for( int i = begin; i <= end; i++ ){
    buffer.append( array[i] );
    if( i+1 < end )
      buffer.append( ", " );
  }
  return buffer.toString();
}
```

Beim ü weiss ich leider keinen Rat.

mfg Beni


----------



## Ecky (28. Jun 2004)

Also den Begriff "Overkill" kenn ich noch nicht.
:-(
Hört sich aber nicht gut an. Was bedeutet dass? Das irgendein Speicher oder so etwas voll läuft?
Danke für den Code. Ich muss mich da aber erst noch reinlesen, hab noch nicht so viel Ahnung.
tschau


----------



## Ecky (29. Jun 2004)

Danke Beni, dein Tip hat mir geholfen!
Hab die Methode allerdings nach meinen Bedürfnissen umgeschrieben.
Hab den kompletten Code nochmal dran gehangen.
Aber was Overkill ist, kannst du mir ja gern noch einmal erklären.

tschau



```
// diese Klasse wird von einer anderen aufgerufen und erhält von dort auch die Argumente
// sie kann vorrangig mehrere ".txt" Dateien auslesen und in einer anderen ".txt" Datei zusammen fassen
// z.B. Dos-Eingabeaufforderung "java KlasseDie_DateiZusammenAufruft_UndArgsÜbergibt Datei1.txt Datei2.txt Ergebnis.txt"

import java.io.*;
import java.util.Arrays;


public class DateiZusammen {


	private String argumente[];
	private int anzArgumente;
	private boolean pruefung; //Gibt Status, ob Methode zum ausgeben des Vorganges gestartet werden darf



    public DateiZusammen (String argumente[]) {  //erhält die Array Liste, durch eine andere Klasse (z.B.args aus main-Methode)
		this.argumente = argumente;              //Array Liste wird im eigenen Array abgespeichert
		anzArgumente = argumente.length;
	}



    public void appendFiles() {
	  pruefung = false;
      try {
          for (int i=0; i<anzArgumente-1; i++) {  //die Schleife läuft so oft wie Argumente übergeben wurden -1
            BufferedReader lesen = new BufferedReader(new FileReader(argumente[i]));
            BufferedWriter schreiben = new BufferedWriter(new FileWriter(argumente[anzArgumente-1],true));
            //true, damit die Dateien angehängt und nicht überschrieben werden

            String uebertragen;
            while ((uebertragen = lesen.readLine()) !=null)
              schreiben.write(uebertragen);
              schreiben.write(" ");
              lesen.close();
              schreiben.close();
          }
          pruefung = true; //wenn Schreibvorgang erfolgreich beendet ist, wird pruefung auf true gesetzt
      }

      catch (Exception e) {
          e.printStackTrace();
      }
    }


    public void ausgeben () {                     //Kann aufgerufen werden, wenn Vorgang auf Bildschirm ausgegeben werden soll
        StringBuffer buffer = new StringBuffer(); //StringBuffer fügt Text hinzu
        if (pruefung == true) {
  	       int ende = anzArgumente-2;             //damit nur die Quelldateien aufgelistet werden
	    	   for (int i=0; i<=ende; i++) {
	    		   buffer.append(argumente[i]);
	       		   if(i+1 <= ende) {
	   			   buffer.append(", ");
	       		   }

	    		   else {
	    		   buffer.append(" wurden in "+ argumente[anzArgumente-1]+ " zusammengefügt!");
	    		   }
	    	   }
	    System.out.println(buffer.toString());
	    }
	}
}
```


----------



## DrZoidberg (29. Jun 2004)

```
try {
    System.setOut(new java.io.PrintStream(System.out, true, "cp850"));
} catch(Exception e) {
    e.printStackTrace();
}
        
System.out.println("ÄÜÖäüöß");
```


----------



## Beni (29. Jun 2004)

Mit Overkill meinte ich, ein bisschen viel rechnen, für ein Resultat, dass man auch einfacher haben kann.
In deinem Fall hast du eine Liste erstellt, was die Initialisierung eines weiteren Arrays bedeutet, nur um einen kleinen String herzustellen.
Das halte ich, persönliche Meinung, für "übertrieben" aufwändig.

Grüsse Beni


----------



## DrZoidberg (29. Jun 2004)

Beni hat gesagt.:
			
		

> Mit Overkill meinte ich, ein bisschen viel rechnen, für ein Resultat, dass man auch einfacher haben kann.
> In deinem Fall hast du eine Liste erstellt, was die Initialisierung eines weiteren Arrays bedeutet, nur um einen kleinen String herzustellen.
> Das halte ich, persönliche Meinung, für "übertrieben" aufwändig.




Zitat aus der Java API Doku:


> public static List asList(Object[] a)
> Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)




Es wird kein weiteres Array angelegt sondern die Liste greift einfach auf das schon existierende Array zu . Tatsächlich wird bei dem Aufruf

```
System.out.println(Arrays.asList(argumente));
```

Lediglich ein List Objekt erstellt aber kein Array erzeugt oder grössere Mengen an Daten kopiert.
Es ist also eine sehr elegante Lösung.


Dein Vorschlag dagegen -

```
public static String list( String[] array, int begin, int end ){
  StringBuffer buffer = new StringBuffer();
  for( int i = begin; i <= end; i++ ){
    buffer.append( array[i] );
    if( i+1 < end )
      buffer.append( ", " );
  }
  return buffer.toString();
}
```

Da wird zuerst ein StringBuffer Objekt erzeugt, welches ein neues Array erstellt und in dieses interne Array des StringBuffers werden dann die Elemente aus deinem Array kopiert.
Dann wird daraus ein String Objekt erstellt, welches ebenfalls ein Array beinhaltet. Es wird dann also der Inhalt des StringBuffer Arrays noch einmal umkopiert in ein weiteres Array.

Bei deiner Methode werden also zwei neue Arrays erzeugt und sämtliche chars werden zwei mal umkopiert.
Ich würde das als Overkill bezeichnen.


So. Und nachdem es so einfach war dich davon zu überzeugen, dass du falsch lagst, überzeuge ich dich jetzt davon, dass du doch Recht hattest.

Ein Aufruf von System.out.println(List_Objekt) wird die List.toString() Methode aufrufen, die einen String zurückliefert und  dieser String wird dann ausgegeben. Diese toString Methode macht aber das selbe, das auch deine Methode macht nur noch eine Stufe umständlicher. Mit noch mehr Arrays und rumkopieren.

Von der Performance her ist deine Lösung also besser.
Die Lösung mit der Liste ist allerdings übersichtlicher und sieht eleganter aus.


----------



## bygones (29. Jun 2004)

DrZoidberg hat gesagt.:
			
		

> Dann wird daraus ein String Objekt erstellt, welches ebenfalls ein Array beinhaltet. Es wird dann also der Inhalt des StringBuffer Arrays noch einmal umkopiert in ein weiteres Array.


Das ist nicht richtig


> Anstatt beim Aufruf von toString einen Kopiervorgang zu starten, teilen sich String- und StringBuffer-Objekt nach dem Aufruf das interne Zeichenarray, d.h. beide Objekte verwenden ein- und denselben Puffer. Normalerweise wäre diese Vorgehensweise indiskutabel, denn nach der nächsten Änderung des StringBuffer-Objekts hätte sich dann auch der Inhalt des String-Objekts verändert (was per Definition nicht erlaubt ist).


----------



## Ecky (29. Jun 2004)

Hallo!
Danke für die rege Teilnahme.
Zumindest weiß ich jetzt, was es mit dem Overkill und dem 2.Array auf sich hatte.

Die Zeile:

```
System.out.println(Arrays.asList(argumente)+ "wurden in " +argumente[anzArgumente-1]+ "zusammengef\u00FCgt.");
```

konnt ich aber nicht verwenden, weil diese Methode mir ja den ganzen Inhalt des Arrays ausgegeben hat.
Ich wollte aber den Inhalt des Arrays in einen Satz einbinden und das letzte Argument des Arrays besonders betonen
z.B: "Datei1.txt", "Datei2.txt" wurden in "Ergebnis.txt" eingefügt.
Dabei sollte es aber egal sein, wieviel Argumente das Array beinhaltet. Immer das Letzte sollte von den anderen abgetrennt ausgegeben werden.
Leider weiß ich nicht, ob man der Methode asList() sagen kann, das es das letzte Argument nicht übergeben soll.
In der API-Doc hab ich dazu nicht gefunden.
Deshalb war ich dann mit der Schleife und dem StringBuffer zufrieden.
Wenn es einfacher geht, würde mich das natürlich interessieren.
Aber wie schon gesagt, das letzte Argument soll etwas weiter hinten im Satz ausgegeben werden.


Der Code von DrZoidberg funktioniert nicht richtig:

```
try { 
    System.setOut(new java.io.PrintStream(System.out, true, "cp850")); 
} catch(Exception e) { 
    e.printStackTrace(); 
} 
        
System.out.println("ÄÜÖäüöß");
```

Die Konstruktormethode von PrintStream kann nur ein OutputStream und Boolean Objekt aufnehmen,
Das "cp850" ist zuviel.
Wo muss das denn hin?
Ermöglicht das die Darstellung des "ü" im DosFenster bei WinXP?

Danke für die vielen Antworten, hab viel gelernt.
tschau


----------



## Beni (29. Jun 2004)

@DrZoidberg

Hast in allen Punkten recht. (Hab wohl zuviele schlechte Erfahrungen mit den Collections gemacht  :roll:  )


----------



## DrZoidberg (29. Jun 2004)

Ecky hat gesagt.:
			
		

> Der Code von DrZoidberg funktioniert nicht richtig:
> 
> ```
> try {
> ...



Bei mir funktioniert der Code.
PrintStream hat 3 verschiedene Konstruktoren. Das "cp850" ist nicht zuviel. cp850 ist der Name des Zeichensatzes, der vom Konsolenfenster verwendet wird.
Windows verwendet normalerweise die Kodierung cp1252 Deshalb benutzt Java unter Windows auch standardmässig cp1252.
Nur innerhalb der Konsole wird cp850 verwendet was Java aber nicht weiss. Deshalb muss man das manuell umstellen.


----------



## DrZoidberg (29. Jun 2004)

deathbyaclown hat gesagt.:
			
		

> > Anstatt beim Aufruf von toString einen Kopiervorgang zu starten, teilen sich String- und StringBuffer-Objekt nach dem Aufruf das interne Zeichenarray, d.h. beide Objekte verwenden ein- und denselben Puffer. Normalerweise wäre diese Vorgehensweise indiskutabel, denn nach der nächsten Änderung des StringBuffer-Objekts hätte sich dann auch der Inhalt des String-Objekts verändert (was per Definition nicht erlaubt ist).



Stimmt. Macht hier aber keinen grossen Unterschied für die Entscheidung, welche Methode man nun verwendet.


----------



## Ecky (30. Jun 2004)

Ja,,, mhh,, hab grad mal nachgeschaut.
Ich programmiere auf einem Computer, wo das SDK1.2 installiert ist.
Und der kennt leider nur 2 Konstruktormethoden!

```
Constructor Summary 
PrintStream(OutputStream out) 
          Create a new print stream. 
PrintStream(OutputStream out, boolean autoFlush) 
          Create a new print stream. 
  Method Summary
```

Auf einem anderen Rechner ist das SDK1.4 installiert und ab da kennt er 3 Konstruktormethoden.
Zumindest weiß ich jetzt was mit 850 gemeint ist.
Hab gehört es gibt auch eine 437 Tabelle (wie auch immer das heißt).

Aber auf dem Rechner,auf dem sich das SDk1.4 befindet, ist Windows ME installiert und da funktioniert das "ü" (so glaube ich zumindest).
Also wenn du weißt, wie ich diese 850 dem SDK1.2 übergebe, kannst du gern nochmal schreiben.
Werd aber selber auch auf die Suche gehen.
Wenn ich was gefunden hab, werd ich es in das Bord eintragen.
DANKE!

tschau


----------



## Ecky (30. Jun 2004)

Ich habe zumindest ein Programm im Java Ordner gefunden, das mir den Unicode anzeigt.
Das ist das Programm "native2ascii.exe"
Es gibt für das ü den Unicode: \ufffd aus.
WinXP gibt über die Zeichentabelle \u00FC aus.
Aber keins davon funktioniert bei mir.

Bei \ufffd kommt ein "?"
Bei \u00FC kommt "³"

Kann mal bitte jemand bei sich schauen, was im Dos-Fenster erscheint, wenn er es über die System.out.println Methode ausgibt?
Bei dem ä und ß funktioniert der UNICode.

Die Tastenkombination ALT+0129 gibt ein "ü" aus.
Kann ich das auch Java übergeben?

Hat jemand den Unicode für ein "ü" ?
Es kann doch nicht so schwer sein, über die Dos-Aufforderung ein ü auszugeben!!!!!

tschau


----------



## DrZoidberg (30. Jun 2004)

Schade, dass es in 1.2 nicht drin ist.

native2ascii gibt für das "ü" auch \u00FC aus.
Bedenke, dass auch das native2ascii Programm nicht weiss, dass das Konsolenfenster eine andere Kodierung verwendet. Wenn du native2ascii in der Konsole startest und dann ein ü eintippst, dann wird der cp850 Code des ü an das antive2ascii Programm geleitet. native2ascii denkt aber es handele sich um einen cp1252 Code und gibt deshalb ein falsches Ergebnis aus. In diesem Fall \ufffd.

Der korrekte Unicode für ü ist also \u00FC.

Das hilft dir jetzt aber überhaupt nicht weiter. Es ist egal ob du das ü direkt in deinen Quellcode schreibst oder stattdessen \u00FC hinschreibst. Die Ausgabe wird die Gleiche sein.
Der Java Compiler erkennt das ü im Quellcode nämlich korrekt, weil der Quellcode im cp1252 Format gespeichert ist, was unter Windows das Standardformat ist, auf das sich Java einstellt.
Das ü wird also völlig korrekt erkannt und in der .class Datei wird daher auch der korrekte Unicode für das ü gespeichert.

Das Problem ist die Ausgabe. Java benutzt nämlich intern nur Unicode. Bei der Ausgabe werden die Unicode Zeichen erst in ein anderes Format umgewandelt bevor es ausgegeben wird. Das ist unter Windows normalerweise 1252.
Wenn du Java nicht dazu bringen kannst das Format auf 850 umzustellen, dann kannst du dir immer noch eine eigene Umwandlungsroutine basteln.

z.B. so


```
public static void printuml(String s) {
        for(int i=0; i<s.length(); i++) {
            char c=s.charAt(i);
            if(c=='ü') System.out.write(129);
            else System.out.print(c);
        }
    }
```

Der Code gibt einen String aus. Wenn er dabei auf ein ü stösst, gibt er den Code 129 aus. Das kann man natürlich noch erweitern für andere Umlaute.


----------

