Java-Compilerplattform-Dateicodierungsproblem

8

Dies ist mein erster Beitrag, um einen Überlauf zu stapeln. Ich mache Java seit 1998, also bin ich kein Anfänger. Kürzlich stieß ich auf ein Problem mit der Kodierung von Dateizeichen, an das ich mich nicht erinnern kann. Es ist durchaus üblich, sich der Zeichencodierung von Textdateien bewusst zu sein und Code zu schreiben, der die Codierung korrekt behandelt, wenn sie auf verschiedenen Plattformen ausgeführt wird. Aber das Problem, das ich fand, wurde von compilation auf einer anderen Plattform als der Ausführungsplattform verursacht. Das war völlig unerwartet, denn nach meiner Erfahrung, wenn javac eine Klassendatei erstellt, sind die wichtigen Parameter java source und target params und die Version des JDK, die die Kompilierung durchführt. In diesem Fall verhalten sich Klassen, die mit JDK 1.6.0_22 unter Mac OS X kompiliert wurden, anders als Klassen, die unter Linux mit 1.6.0_23-b05 kompiliert wurden, wenn sie unter Mac OS X ausgeführt wurden. Die angegebene Quelle und das Ziel waren 1.4.

Eine Zeichenfolge, die als ISO-8859_1 im Speicher codiert wurde, wurde mit einer PrintStream println-Methode auf die Festplatte geschrieben. Abhängig davon, auf welcher Plattform der Java-Code COMPILIERT wurde, wurde die Zeichenfolge anders geschrieben. Dies führte zu einem Fehler. Die Fehlerbehebung für den Fehler bestand darin, die Dateicodierung beim Schreiben und Lesen der Datei explizit anzugeben.

Was mich überraschte, war, dass das Verhalten davon abhing, wo die Klassen kompiliert wurden und nicht auf welcher Plattform die Klasse ausgeführt wurde. Ich kenne Java-Code sehr gut, wenn er auf verschiedenen Plattformen ausgeführt wird. Aber es ist ein wenig gruselig, wenn derselbe Code, der auf verschiedenen Plattformen kompiliert wurde, auf derselben Plattform anders läuft .

Ist jemand auf dieses spezifische Problem gestoßen? Es scheint schlecht für jeden Java-Code zu sein, der Strings in Datei liest und schreibt, ohne die Zeichencodierung explizit anzugeben. Und wie oft ist das erledigt?

Danke,

Richard Brewster Ссылка

    
Richard Brewster 07.02.2011, 22:48
quelle

4 Antworten

7

Es gibt keine solchen Dinge wie eine Zeichenfolge, die als ISO-8859-1 im Speicher codiert wurde. Java-Zeichenfolgen im Speicher sind immer Unicode-Zeichenfolgen. (In UTF-16 kodiert, aber das brauchst du jetzt nicht wirklich).

Die Kodierung kommt nur dann zum Einsatz, wenn Sie die Zeichenfolge eingeben oder ausgeben. Wenn keine explizite Kodierung verwendet wird, verwendet sie die Systemvorgabe (die auf einigen Systemen von Benutzereinstellungen abhängt).

Wie von McDowell gesagt, sollte die tatsächliche Kodierung Ihrer Quelldatei mit der Kodierung übereinstimmen, die Ihr Compiler von Ihrer Quelldatei erwartet, sonst bekommen Sie Probleme, wie Sie beobachtet haben. Sie können dies auf verschiedene Arten erreichen:

  • Verwenden Sie die Option -encoding des Compilers und geben Sie die Codierung Ihrer Quelldatei an. (Mit ant setzen Sie den Parameter encoding= .)
  • Verwenden Sie Ihren Editor oder ein anderes Tool (wie recode ), um die Kodierung Ihrer Datei in den Compilerstandard zu ändern.
  • Verwenden Sie native2ascii (mit der richtigen Option -encoding ), um Ihre Quelldatei in ASCII mit \uXXXX -escapes zu übersetzen.

Im letzten Fall können Sie diese Datei später überall mit jeder Standardkodierung kompilieren, also könnte dies der Weg sein, wenn Sie den Quellcode an nicht für die Kodierung verantwortliche Personen weitergeben, die irgendwo kompiliert werden sollen.

Wenn Sie ein größeres Projekt haben, das aus mehr als einer Datei besteht, sollten alle dieselbe Codierung haben, da der Compiler nur einen solchen Schalter hat, nicht mehrere.

In allen Projekten, die ich in den letzten Jahren hatte, kodiere ich immer alle meine Dateien in UTF-8 und setze in meiner Ameisen-Builddatei den encoding="utf-8" -Parameter auf die javac-Aufgabe. (Mein Editor ist intelligent genug, um die Kodierung automatisch zu erkennen, aber ich setze den Standardwert auf UTF-8.)

Die Codierung ist für andere Quellcode-Bearbeitungstools wie javadoc von Bedeutung. (Dort sollten Sie zusätzlich die Optionen -charset und -docencoding für die Ausgabe haben - sie sollten übereinstimmen, können aber von der Quelle abweichen - -encoding .)

    
Paŭlo Ebermann 07.02.2011 23:35
quelle
4

Ich würde vermuten, dass es während der Kompilierungsphase ein Transcodierungsproblem gibt und der Compiler keine Richtung bezüglich der Codierung einer Quelldatei hat (siehe z. B. den Javac -encoding wechseln).

Compiler verwenden im Allgemeinen die Standardkodierung des Systems, wenn Sie nicht spezifisch sind, was dazu führen kann, dass String- und Char-Literale beschädigt werden (intern verwendet Java Bytecode ein modifiziertes UTF-8-Formular, so dass Binaries portabel sind). Nur so kann ich mir vorstellen, dass Probleme zur Kompilierzeit auftreten.

Ich habe ein bisschen darüber geschrieben hier .

    
McDowell 07.02.2011 23:13
quelle
1

Ich hatte ähnliche Probleme bei der Verwendung von Variablennamen, die nicht ascii sind (Σ, σ, Δ, usw.), wenn math formula ausgeführt wird. Unter Linux verwendete es beim Interpretieren die UTF-8-Codierung. Unter Windows beschwerte er sich über ungültige Namen, weil Windows ISO-LATIN-1 verwendet. Die Lösung bestand darin, die Codierung im ant-Skript anzugeben, mit dem ich diese Dateien kompiliert habe.

    
KitsuneYMG 07.02.2011 23:47
quelle
0

Verwenden Sie immer Escape-Codes (z. B. \uxxxx ) in Ihren Quelldateien, und dies ist kein Problem. @Paulo hat das erwähnt, aber ich wollte es explizit aufrufen.

    
jtahlborn 08.02.2011 00:25
quelle

Tags und Links