Sonderzeichen aus Datei einlesen und in Datei ausgeben.

Ratte78

Mitglied
Hallo Leute,

vorab: Ich möchte nichts weiter tun als eine .csv Datei einzulesen, die Daten zu konvertieren und in eine .csv-Datei wieder auszugeben. Hab da aber Probleme mit Sonderzeichen. Insbesondere "µ".
Die Eingagsdatei wird aus Excel exportiert. Hat also als Zeichensatz vermutlich Cp1252.
Ich lese die ein mit org.apache.commons.csv. Mit Angabe der Codierung:
java:
FileInputStream is = new FileInputStream(IN_CSV_FILE_PATH);
Reader in = new InputStreamReader(new BOMInputStream(is), "UTF-8"); //aus Excel als csv-UTF-8 exportiert mit einlesen mit BOM per org.apache.commons.io.input.BOMInputStream
CSVFormat fmt = CSVFormat.EXCEL.withFirstRecordAsHeader().withRecordSeparator(';').withDelimiter(delimiter)
.withQuote('"').withQuoteMode(QuoteMode.NON_NUMERIC); // delimiter ist ";" oder ","
Iterable<CSVRecord> records = fmt.parse(in);
int rows = 0;
for (CSVRecord record : records) {
rows++;
... Hier erfolgt die Konvertierung
... Ausgabe:
wurde folgendermasen definiert:
pwr = new OutputStreamWriter(new FileOutputStream(OUT_CSV_FILE_PATH), "Cp1252");

usw.

In der Eingangsdatei wird das "µ" korrekt angezeigt. Aber irgendwie kann es von Java nicht korrekt eingelesen oder ausgegeben werden.
Meines Wissens wandelt java alles erstmal nach unicode um und dann wieder zurück. Im unicode ist das Zeichen aber def. enthalten.
Ich hab keine Ahnung was ich falsch mache.
Ich hoffe auf eure Hilfe. Und bedanke mich bereits im vorraus.

Gruß
Ratte

ps: Das mit der Code-Definition hab ich nicht verstanden. Also wenn mir da schon mal jemand helfen könnte? 😎
 
Servus Robert,

danke für deine Antwort.
Ich hab mich aber unklar ausgedrückt: Ich hab zuerst versucht die Datei aus Excel als CSV zu exportieren(Ist dann Cp1252). Dann wird das Mühselige "µ" auch im Texteditor angezeigt. Aber beim einlesen und dann ausgeben(als Cp1252) wird das "µ" zu "?". Habs dann mit Export von Excel als CSV-UTF8 probiert. Deswegen auch dann mit BOMInputStream eingelesen. Beim ausgeben als UTF-8 wird aus dem ? eine wirre Zeichenfolge.

Ganz sicher fehlt es mir an Information oder ich versteh irgendwas falsch.
Irgend eine Idee?

Danke
 
Mach die Datei mal in Notepad++ auf, da kannst du schnell den Zeichensatz ändern. Wenn du einen findest, mit dem's klappt, dann verwende den in Java zum Einlesen.
 
Ich hab zuerst versucht die Datei aus Excel als CSV zu exportieren(Ist dann Cp1252). Dann wird das Mühselige "µ" auch im Texteditor angezeigt. Aber beim einlesen und dann ausgeben(als Cp1252) wird das "µ" zu "?".
Ja, dann musst du in Java auch "CP1252" als Charset angeben.
Habs dann mit Export von Excel als CSV-UTF8 probiert. Deswegen auch dann mit BOMInputStream eingelesen. Beim ausgeben als UTF-8 wird aus dem ? eine wirre Zeichenfolge.
Dein Text-Editor ist ein Arsch und zeigt dir UTF-8 Dateien als CP-1252 an. Zur Erklaerung, bei UTF-8 ist alles oberhalb von 128(?) als Zwei-Byte-Sequenz dargestellt. also ein "ü" braucht zwei Bytes in UTF-8, das erste gibt die Codepage an, das zweite das Zeichen in dieser Codepage.

Das Thema Enkodierung ist etwas leidig, du brauchst einen Text-Editor welcher es dir erlaubt zwischen den Enkodierungen umzuschalten in der Datei welche du gerade betrachtest (das ist so ziemlich jeder, mit Ausnahme Notepad natuerlich). So einer wie Notepad++ oder Geany zum Beispiel. Erst dann kannst du wirklich anfangen "richtig" zu pruefen was deine Java Logik macht.
 
hier etwas was eine datei im cp1252 liest und als utf8 speichert.

Java:
public static void main(String[] args) throws Exception
    {
        File file = new File("test.txt");
        File file2 =new File("test2.txt");
        StringBuilder builder = new StringBuilder();

        Reader reader = new InputStreamReader(new FileInputStream(file), "windows-1252");
        while (reader.ready())
        {
           char ch = (char) reader.read();
           builder.append(ch);
        }
        reader.close();

        String string = builder.toString();
             
        Writer writer = new OutputStreamWriter(new FileOutputStream(file2), "UTF8");
        writer.write(string);
        writer.flush();
        writer.close();
    }
 
Zuletzt bearbeitet:
Morgen Leute.
Vielen Dank für eure Antworten. Werde die Datei mal mit Notepad++ bzw. einem Hex-Editor prüfen.
Derweil hab ich das Programm in Eclipse debugged und mir das entsprechende Feld im Debugger angesehen. Passt: µ = µ.
Ein System.out.println bringt im Console-Window aber wieder nur ein "?". So wird es auch in die Ausgangsdatei geschrieben.
Ein System.out.println("µ") funktioniert allerdings.Der Eclipse-Editor ist auf Cp1252 eingestellt.
Ich bin völlig verwirrt.
Gruß Ratte
 
Morgen Leute.
Vielen Dank für eure Antworten. Werde die Datei mal mit Notepad++ bzw. einem Hex-Editor prüfen.
Derweil hab ich das Programm in Eclipse debugged und mir das entsprechende Feld im Debugger angesehen. Passt: µ = µ.
Ein System.out.println bringt im Console-Window aber wieder nur ein "?". So wird es auch in die Ausgangsdatei geschrieben.
Ein System.out.println("µ") funktioniert allerdings.Der Eclipse-Editor ist auf Cp1252 eingestellt.
Ich bin völlig verwirrt.
Gruß Ratte
Der Zeichensatz des Editors in Eclipse ist irrelevant. Der besagt nur, in welchem Zeichensatz dein Quellcode gespeichert wird, das hat nichts mit irgendwelchen Ein- oder Ausgabedateien zu tun (hier verwende ich mittlerweile grundsätzlich UTF-8, da wir auf verschiedenen Systemen arbeiten).

Was ist ein "Feld" in Eclipse? Wenn das Zeichen im Java-String richtig gespeichert ist, dann hat das Einlesen richtig funktioniert.

Was die Ausgabe betrifft, führe mal bitte diesen Code aus:
Java:
    public static void main(String[] args) {
        System.out.println("µ");
    }

Kommt das Zeichen richtig auf der Konsole an?
Falls ja, dann wurde die Datei wohl doch nicht korrekt eingelesen.
Falls nein, dann hast du ein Problem mit dem Zeichensatz deiner Konsole.
Überprüf gegebenenfalls auch mal den Zahlenwert des Characters (Fisch dir das Zeichen mit charAt() raus und lass es als Int ausgeben).

Hier fehlen leider doch ein paar Informationen bezüglich der Umsetzung. Ein geht/geht nicht sagt nicht wirklich viel aus.
Mit welchem Charset hast du die Quelldatei eingelesen?
Mit welchem Charset hast du die Zieldatei geschrieben?
Poste eventuell doch auch einfach mal den Code für's Einlesen (in Code Tags bitte).
 
Cp1252 wie in Windows benutzt wird ist ein 8 Bit Zeichen Code. (256 Zeichen theoretisch möglich)
Die ersten 127 Zeichen entsprechen den Ansi ASCII Code danach kommt die Codepage .
Dein „µ“ hat da den Code Hex 0xB5 Dezimal 181.



UTF 8 ist ein 16 Bit Zeichen Code. (65536 Zeichen theoretisch möglich)
Die ersten 127 Zeichen sind auch wider Ansi ASCII Code
Von 0x80 bis 0xBF ist frei wird mit meistens mit „?“ oder einen anderen Symbol oft ein kleines Quadrat angezeigt.
Dein „µ“ hat bei UTF8 0xC2B5 in hex


In Java hat ein Zeichen immer 16 Bit .
Deshalb caste ich auch das Byte was vom Reader gelesen wird zu Char 16 Bit.
 
Das Fragezeichen hat noch irgendwo in meinem Hinterkopf rumort. Hab das mal getestet.
Dafür habe ich testweise eine ANSI und eine UTF-Datei mit je einer Zeile "µ" erstellt, ein Fragezeichen kam nie auf der Konsole an.

Java:
    public static void main(String[] args) {
        System.out.println("µ");
        try {
            for (String charsetname : Arrays.asList("windows-1252", "utf-8")) {
                for (String filename : Arrays.asList("e:\\my_ansi.txt", "e:\\my_utf.txt")) {
                    System.out.printf("Reading '%s' with charset '%s': ", filename, charsetname);
                    try ( var r = new BufferedReader(new FileReader(filename, Charset.forName(charsetname)))) {
                        System.out.println(r.readLine());
                    }
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(MyOhMy.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
Ausgabe:
Code:
µ
Reading 'e:\my_ansi.txt' with charset 'windows-1252': µ
Reading 'e:\my_utf.txt' with charset 'windows-1252': µ
Reading 'e:\my_ansi.txt' with charset 'utf-8': �
Reading 'e:\my_utf.txt' with charset 'utf-8': µ

Kann es sein, dass dein CSVFormat hier was verfälscht? An welchem Punkt hast du debugt?
 
Das Fragezeichen hat noch irgendwo in meinem Hinterkopf rumort. Hab das mal getestet.
Dafür habe ich testweise eine ANSI und eine UTF-Datei mit je einer Zeile "µ" erstellt, ein Fragezeichen kam nie auf der Konsole an.


[/CODE]
Ausgabe:
Code:
µ
Reading 'e:\my_ansi.txt' with charset 'windows-1252': µ
Reading 'e:\my_utf.txt' with charset 'windows-1252': µ
Reading 'e:\my_ansi.txt' with charset 'utf-8': �
Reading 'e:\my_utf.txt' with charset 'utf-8': µ
das "?" wird von einigen Editoren angezeigt wenn zum Beispiel er ein Zeichen im Utf8 Zeichensatz erwartet aber es im cp1252 ist. Denn das 0xB5xx gibt es im UTF8 Zeichensatz nicht also fügt der Editor einen Platzhalter dafür ein. Einige benutzen halt das „?“
 
das "?" wird von einigen Editoren angezeigt wenn zum Beispiel er ein Zeichen im Utf8 Zeichensatz erwartet aber es im cp1252 ist. Denn das 0xB5xx gibt es im UTF8 Zeichensatz nicht also fügt der Editor einen Platzhalter dafür ein. Einige benutzen halt das „?“
Ja, aber er hat gesagt, es wäre auf der Konsole ausgegeben worden.
 
Zum Thema System.out.printl
Dann schaut euch doch mal an welchen Zeichensatz die Konsole Standard mäßig benutzt.
Dann stellt doch mal die Ausgabe auf einen andren Zeichensatz um.

Java:
 System.out.println("schönes München");
            System.setOut(new PrintStream(
                    new FileOutputStream(FileDescriptor.out),true,"CP850"));
 System.out.println("schönes München");


und schaut euch die Ausgabe an.

schönes München
sch�nes M�nchen
 
Zum Thema System.out.printl
Dann schaut euch doch mal an welchen Zeichensatz die Konsole Standard mäßig benutzt.
...
Verdammt, Denkfehler meinerseits, hab den Output in der IDE geprüft und nicht in einem DOS-Fenster.
Dass die ISO850 verwenden, weiß ich, seit ich Batch-Dateien bei einem norwegischen Kunden erstellen musste.

Dann hat sich meine Überlegung wohl erübrigt.
 
Konsolen-Anwendung (insbesondes unter Windows) war auch für mich neu. Hab den Zeichensatz per: System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, "CP850")); angepasst.

Aber hab Dank für deinen Beitrag. Deine Überlegungen sind keineswegs vergebens. Irgendwann wird irgendwer über diesen Post stolpern und bekommt einen neuen Denkanstoß.

Also: Weiter so ........
 

Zurück
Oben