2009-04-07 12 views
0

Ich habe eine kleine Anwendung geschrieben, die einige Textmanipulationen durchführt und die Ausgabe in eine Datei schreibt (html, csv, docx, xml) und das scheint alles unter Mac OS X zu funktionieren Allerdings scheint es, dass ich Probleme mit der Zeichencodierung bekomme und viele "" verschwinden und werden durch seltsame Dinge ersetzt. Normalerweise ist das Schließen eines Paares.Character Encoding Trouble - Java

Ich benutze einen FreeMarker, um meine Ausgabedateien zu erstellen, und es gibt ein Array byte [] und in einem Fall auch einen ByteArrayStream zwischen dem Lesen der Templates und dem Schreiben der Ausgabe. Ich nehme an, dass dies ein Zeichencodierungsproblem ist, also wenn mich jemand beraten oder auf eine "Best Practice" -Ressource für den Umgang mit Zeichenkodierung in Java hinweisen könnte.

Dank

Antwort

5

Es gibt wirklich nur eine Best Practice: bewusst sein, dass Strings und Bytes sind zwei grundverschiedene Dinge, und dass, wenn Sie konvertieren zwischen ihnen, Sie verwenden eine Zeichencodierung (entweder implizit oder explizit), auf die Sie achten müssen.

Typische Problemstellen in der Java API sind:

  • new String(byte[])
  • String.getBytes()
  • FileReader, FileWriter

Alle diese implizit die Plattform Standard-Codierung verwenden, die auf dem Betriebssystem abhängt und Gebietsschemaeinstellungen des Benutzers. Normalerweise ist es eine gute Idee, dies zu vermeiden und explizit eine Kodierung in den obigen Fällen zu deklarieren (was FileReader/Writer leider nicht erlaubt, also müssen Sie einen InputStreamReader/Writer verwenden).

Ihre Probleme mit den Anführungszeichen und Ihre Verwendung einer Vorlage-Engine können jedoch eine viel einfachere Erklärung haben. Mit welchem ​​Programm schreiben Sie Ihre Vorlagen? Es klingt, als wäre es eine, die "smart quotes" einfügt, die Teil der Windows-spezifischen cp1251-Codierung sind, aber nicht in der globaleren ISO-8859-1-Codierung existieren.

Wahrscheinlich müssen Sie wissen, in welcher Kodierung Ihre Vorlagen gespeichert sind, und Ihre Vorlagen-Engine so konfigurieren, dass diese Kodierung beim Einlesen der Vorlagen verwendet wird. Beachten Sie auch, dass einige texxt-Dateien, insbesondere XML, die Codierung explizit in einer Kopfzeile deklarieren, und wenn diese Kopfzeile nicht mit der tatsächlichen Codierung übereinstimmt, die von der Datei verwendet wird, werden Sie ständig Probleme haben.

+0

Ich verwende FreeMarker und das Template-Objekt, das ich erstelle, scheint CP1251 zu verwenden, obwohl es auch in einem anderen Feld behauptet, UTF-8 zu verwenden. Und sie tun, wie typografische Anführungszeichen erscheinen, aber die ‚"‘kommen nicht von meinem tempalte aber aus dem Text, den ich als Eingabe am Parsen. – willcodejavaforfood

+0

Dann scheint das Problem sowohl von Freemarker in der Konfiguration zu sein (im Widerspruch zu Codierungen sind immer sehr schlechte Nachrichten) und in der Parsing-Code. –

+0

ich btw UTF-8 in meinen xML und hTML-Dateien angegeben habe. vm Eigenschaft das Template-Objekt nicht mehr zeigt im Widerspruch zu Kodierungen Nach der Verwendung. – willcodejavaforfood

3

Sie können steuern, die Kodierung der JVM mit f, indem ausgeführt wird, ex

-Dfile.encoding = utf-8

für (UTF-8 natürlich) als Argument für die JVM. Dann sollten Sie auf allen Plattformen vorhersehbare Ergebnisse erzielen. Beispiel:

java -Dfile.encoding = utf-8 my.MainClass

+0

Diese sicher zu beheben Alles, Prost Mate – willcodejavaforfood

+0

Es ist jedoch nur eine Pflaster-Lösung, die das eigentliche Problem für jetzt verstecken kann, nur um später wieder auftauchen. –

1

Das Ausführen der JVM mit einer "Standard" -Encodierung über den verwirrenden Namen -Dfile.encoding löst viele Probleme.

Sicherstellen, dass Ihre App keine byte[] <-> String Conversions ohne Codierung verwendet, ist wichtig, da Sie die VM-Codierung (z.Wenn Sie einen App-Server haben, der von mehreren Anwendungen verwendet wird)

Wenn Sie durch das ganze Kodierungsproblem verwirrt sind, oder Ihr Wissen revidieren wollen, schrieb Joel Spolsky eine great article auf diesem.

0

musste ich sicherstellen, dass der Output die richtige Codierung

OutputStream out = ... 
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8"); 
template.process(model, writer); 

Plus, wenn Sie ein ByteArrayOutputStream auch sicherstellen, verwenden anrufen toString mit der richtigen Codierung verwendet: Haben

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
... 
baos.toString("UTF-8");