1. Java -Codierungsprozessprozess
Wir verwenden immer eine Java -Klassendatei, um mit den Benutzern am direkten (Eingabe, Ausgabe) zu interagieren, und der in diesen interaktive Inhalt enthaltene Text kann Chinese enthalten. Unabhängig davon, ob diese Java-Klassen mit der Datenbank oder mit der Front-End-Seite interagieren, ist ihr Lebenszyklus immer wie folgt:
(1) Programmierer schreiben Programmcode über einen Editor im Betriebssystem und speichern das Betriebssystem im Format von .java. Wir nennen diese Dateien die Quelldateien.
(2) Kompilieren Sie diese Quelldateien über Javac.exe in JDK, um die .CLASS -Klasse zu bilden.
(3) Führen Sie diese Klassen direkt aus oder stellen Sie sie in einem Webcontainer bereit, um das Ausgabeergebnis zu erhalten.
Diese Prozesse werden aus der Makroperspektive beobachtet, und es ist definitiv nicht möglich, dies zu verstehen. Wir müssen wirklich verstehen, wie Java codiert und dekodiert ist:
Schritt 1: Wenn wir einen Editor zum Schreiben einer Java -Quelldatei verwenden, verwendet die Programmdatei das Standard -Codierungsformat des Betriebssystems (normalerweise verwendet unser chinesisches Betriebssystem das GBK -Codierungsformat), um eine .java -Datei zu bilden. Die Java -Quelldatei wird in der Datei gespeichert. Codierungsformat, das standardmäßig vom Betriebssystem unterstützt wird. Der folgende Code kann den Datei des Systems anzeigen.
System.out.println (System.getProperty ("file.encoding")); Schritt 2: Wenn wir Javac.exe verwenden, um unsere Java -Datei zu kompilieren, bestätigt JDK zunächst seine Kompilierungsparametercodierung, um den Quellcode -Zeichensatz zu bestimmen. Wenn wir den Kompilierungsparameter nicht angeben, erhält JDK zunächst den Standarddatei des Betriebssystems. Codierungsparameter. Anschließend konvertiert JDK das Java -Quellprogramm, das wir aus der Datei geschrieben haben.
Schritt 3: JDK schreibt die kompilierten und gespeicherten Informationen auf dem obigen Speicher in die Klassendatei in Form einer .CLASS -Datei. Zu diesem Zeitpunkt ist die .Class -Datei Unicode codiert, was bedeutet, dass die Inhalte in unseren gemeinsamen .class -Dateien in das Unicode -Codierungsformat konvertiert werden, unabhängig davon, ob sie chinesische oder englische Zeichen sind.
In diesem Schritt ist die Handhabungsmethode von JSP -Quelldateien etwas anders: Der Web -Container ruft den JSP -Compiler auf. Der JSP -Compiler prüft zunächst, ob die JSP -Datei das Dateicodierungsformat hat. Wenn es nicht festgelegt ist, ruft der JSP -Compiler den JDK auf, um die JSP -Datei mithilfe der Standard -Codierungsmethode in eine temporäre Servlet -Klasse umzuwandeln, und kompilieren Sie sie dann in eine .class -Datei und behalten Sie sie in einem temporären Ordner.
Schritt 4: Führen Sie die kompilierte Klasse aus: Hier werden mehrere Situationen stattfinden
(1) Direkt auf der Konsole laufen.
(2) JSP/Servlet -Klasse.
(3) Zwischen der Java -Klasse und der Datenbank.
Jede dieser drei Situationen wird unterschiedliche Möglichkeiten haben.
1. Klassen, die auf der Konsole laufen
In diesem Fall wird der JVM zunächst die im Betriebssystem gespeicherte Klassendatei in den Speicher gelesen. Zu diesem Zeitpunkt ist die Klassendatei im Speicher in Unicode codiert, und dann wird die JVM sie ausführen. Wenn der Benutzer Informationen eingeben muss, werden die Informationen des Benutzers in der Datei codiert. Codierungsformat und konvertiert in das Unicode -Codierungsformat, um es im Speicher zu speichern. Nachdem das Programm ausgeführt wurde, wird das Ergebnis in Datei.Codierungsformat konvertiert und in das Betriebssystem und in die Schnittstelle ausgegeben. Der gesamte Prozess ist wie folgt:
Im gesamten obigen Vorgang können bei keiner Codierungsumwandlung keine Fehler auftreten, ansonsten treten auf verstümmelten Code auf.
2. Servlet -Klasse
Da JSP -Dateien irgendwann in Servlet -Dateien konvertiert werden (der Speicherort ist jedoch unterschiedlich), werden wir hier auch JSP -Dateien einbeziehen.
Wenn ein Benutzer ein Servlet fordert, ruft der Web -Container seine JVM auf, um das Servlet auszuführen. Zunächst lädt der JVM die Servlet -Klasse in den Speicher. Der Servlet -Code im Speicher befindet sich im Unicode -Codierungsformat. Dann führt das JVM das Servlet im Speicher aus. Wenn Sie während des Laufs Daten akzeptieren müssen, die vom Client übergeben (z. B. von Formularen und URLs übergebene Daten), akzeptiert der Webcontainer die eingehenden Daten. Während des Empfangsprozesses wird das Set -Codierungsformat angewendet, wenn das Programm die Codierung eingehender Parameter festlegt. Wenn es nicht festgelegt ist, wird das Standard-ISO-8859-1-Codierungsformat angewendet. Nach den empfangenen Daten konvertiert der JVM das Codierungsformat in Unicode und speichert es im Speicher. Nach dem Ausführen des Servlets werden die Ausgangsergebnisse generiert, und das Codierungsformat dieser Ausgangsergebnisse ist immer noch Unicode. Unmittelbar danach sendet der Webcontainer die generierte Unicode -Codierungsformat -Zeichenfolge direkt an den Client. Wenn das Programm zum Zeitpunkt der Ausgabe das Codierungsformat angibt, wird es gemäß dem angegebenen Codierungsformat in den Browser ausgegeben. Andernfalls wird das Standard-ISO-8859-1-Codierungsformat angewendet. Das gesamte Prozessflussdiagramm lautet wie folgt:
1. Datenbankteil
Wir wissen, dass die Verbindung zwischen Java-Programmen und Datenbanken über den JDBC-Treiber und das JDBC-Treiber standardmäßig mit dem ISO-8859-1-Codierungsformat verbunden ist. Das heißt, wenn wir Daten über das Java-Programm an die Datenbank übergeben, konvertiert JDBC die Daten zunächst im Unicode-Codierungsformat in das ISO-8859-1-Codierungsformat und speichern sie dann in der Datenbank, dh wenn die Datenbank Daten speichert, das Default-Format ist ISO-8859-1.
2. Codierung und Dekodierung
Das Folgende beendet die Codierungs- und Dekodierungsoperationen, die Java in diesen Gelegenheiten ausführen muss, und sortieren den Zwischenprozess im Detail, um den Codierungs- und Dekodierungsprozess von Java weiter zu beherrschen. Es gibt vier Hauptszenarien in Java, die Codierung und Dekodierung erfordern:
(1): E/A -Operation
(2): Speicher
(3): Datenbank
(4): Javaweb
Im Folgenden wird hauptsächlich die beiden vorherigen Szenarien vorgestellt. Solange der Datenbankteil richtig eingestellt ist, wird es kein Problem geben. Es gibt zu viele Javaweb -Szenarien, und Sie müssen die Kodierung von URL-, Get-, Post- und Servlet -Dekodierung verstehen, sodass die LZ -Einführung des Javaweb -Szenarios.
1.I/o Betrieb
In der vorherigen LZ erwähnte das verstümmelte Problem nichts anderes als die Inkonsistenz des Codierungsformats während des Transkodierungsprozesses. Zum Beispiel wird UTF-8 zur Codierung verwendet und GBK wird zur Dekodierung verwendet. Der grundlegendste Grund ist jedoch, dass es ein Problem mit Charakter-zu-Byte- oder Byte-zu-Charakter-Konvertierung gibt, und das Hauptszenario der Konvertierung in diesem Fall ist der E/A-Betrieb. Natürlich umfassen E/A -Operationen hauptsächlich Netzwerk -E/A (dh Javaweb) und Disk -E/A. Die Netzwerk -E/A wird im nächsten Abschnitt eingeführt.
Schauen wir uns zunächst die I/A -Codierungsoperation an.
InputStream ist die Superklasse aller Klassen des Byte -Eingangsstroms, und der Leser ist die abstrakte Klasse des Lesers. Java liest Dateien auf eine Weise, die in Byte -Stream und durch Zeichenstream unterteilt ist. InputStream und Reader sind die Superklassen dieser beiden Lesemethoden.
Mit Byte verwenden wir normalerweise die Methode "InputStream.read (), um Bytes im Datenstrom (Read () zu lesen, nur ein Byte zu einem Zeitpunkt, der sehr langsam ist. Wir verwenden normalerweise Read (Byte [])), dann in einem Byte [] -Array speichern und schließlich in String umwandeln. Wenn wir eine Datei lesen, hängt die Codierung der Bytes vom von der Datei verwendeten Codierungsformat ab, und das Codierungsproblem wird auch an der Konvertierung zum String -Prozess beteiligt. Wenn sich die Codierungsformate zwischen den beiden unterscheiden, kann das Problem auftreten. Beispielsweise gibt es ein Problem, dass das Test.txt-Codierungsformat UTF-8 ist, sodass das Datenstrom-Codierungsformat beim Lesen einer Datei über einen Byte-Stream erhalten wird. Wenn wir das Codierungsformat während der Konvertierung in die String nicht angeben, verwenden wir standardmäßig das Decodieren des Systems Codierungsformat (GBK). Da die Codierungsformate der beiden inkonsistent sind, tritt der verstümmelte Code definitiv im Prozess der Konstruktion von String auf wie folgt:
Datei Datei = new Datei ("c: //test.txt"); InputStream input = new FileInputStream (Datei); StringBuffer Buffer = new StringBuffer (); byte [] bytes = neues byte [1024]; für (int n; (n = input.read (bytes))! } System.out.println (Buffer); Das Ausgangsergebnis ist verstümmelt ...
Der Inhalt in test.txt lautet: Ich bin CM.
Um verstümmelten Code zu vermeiden, geben Sie das Codierungsformat während des String -Konstruktionsprozesses so an, dass die Codierungsformate der beiden während der Codierung und Dekodierung konsistent sind:
Buffer.Append (neue String (Bytes, 0, n, "UTF-8");
Durch Zeichen kann der Zeichenstrom als Wrapper -Stream angesehen werden. Die zugrunde liegende Ebene verwendet immer noch einen Byte -Stream, um Bytes zu lesen, und dekodiert dann die Lesebytes mit der angegebenen Codierungsmethode in Zeichen. In Java ist Reader eine Superklasse mit der Aufschrift Charakterströme. Aus der unteren Perspektive gibt es also keinen Unterschied zwischen dem Lesen von Dateien nach Bytes und dem Lesen nach Charakter. Beim Lesen bleibt jedes Mal Bytes und Byte -Streams lesen jeweils ein Byte.
Byte & Character Conversion konvertieren Bytes in Zeichen im Wesentlichen InputStreamReader. Die API wird wie folgt erklärt: InputStreamReader ist die Brücke zwischen dem Byte -Stream zum Zeichenstrom: Sie liest Bytes mit dem angegebenen Zeichensatz und dekodiert sie in Zeichen. Der von ihm verwendete Zeichensatz kann mit dem Namen angegeben oder explizit angegeben werden, oder es kann den Standardzeichen der Plattform akzeptieren. Jeder Aufruf einer Read () -Methode im InputStreamReader führt dazu, dass ein oder mehrere Bytes aus dem zugrunde liegenden Eingabestream gelesen werden. Um eine effektive Konvertierung von Byte in den Charakter zu ermöglichen, können Sie im Voraus weitere Bytes aus dem zugrunde liegenden Strom lesen und die zur Erfüllung des aktuellen Lesevorgangs erforderlichen Bytes überschreiten. Die API -Erklärung ist sehr klar. InputStreamReader verwendet beim Lesen der Datei unten immer noch Byte -Lesen. Nach dem Lesen der Bytes muss es nach einem angegebenen Codierungsformat in Zeichen analysieren. Wenn es kein angegebenes Codierungsformat gibt, wird das System Standard -Codierungsformat übernommen.
String -Datei = "c: //test.txt"; String charset = "utf-8"; // Zeichen zum Konvertieren in Byte Stream FileOutputStream OutputStream = new FileOutputStream (Datei); OutputStreamwriter writer = new outputStreamWriter (outputStream, charSet); versuche {writer.write ("Ich bin cm"); } endlich {writer.close (); } // Bytes lesen, um in Zeichen fileInputStream inputStream = new FileInputStream (Datei) konvertiert zu werden; InputStreamReader Reader = neuer InputStreamReader (InputStream, charSet); StringBuffer Buffer = new StringBuffer (); char [] buf = new char [64]; int count = 0; try {while ((count = reader.read (buf))! = -1) {buffer.append (buf, 0, count); }} endlich {reader.close (); } System.out.println (Buffer); 2. Speicher
Schauen wir uns zunächst den folgenden einfachen Code an
String S = "Ich bin cm"; byte [] bytes = s.getBytes (); String S1 = New String (Bytes, "GBK"); String S2 = New String (Bytes);
In diesem Code sehen wir drei Codierungskonvertierungsprozesse (eine Codierung, zwei Dekodierung). Schauen wir uns zuerst String.gettytes () an:
public byte [] getBytes () {return stringcoding.encode (value, 0, value.length); }Rufen Sie intern die Methode StringCoding.encode () auf:
static byte [] codieren (char [] ca, int off, int len) {String csn = charSet.DefaultCharSet (). name (); Versuchen Sie {// verwenden Sie CharsSet Name EnCode () Variante, die Caching liefert. return codes (csn, ca, off, len); } catch (unportedenCodingException x) {WarnunSupportedCharSet (CSN); } try {return encodes ("ISO-8859-1", ca, off, len); } catch (UnsupportedenCodingException x) {// Wenn dieser Code während der VM -Initialisierung getroffen wird, ist MessageUtils // die einzige Möglichkeit, eine Fehlermeldung zu erhalten. MessageUtils.err ("ISO-8859-1 charSet nicht verfügbar:" + x.toString ()); // Wenn wir ISO-8859-1 nicht finden können (eine erforderliche Codierung), dann sind die Dinge mit der Installation ernsthaft falsch. System.exit (1); null zurückkehren; }}Die Methode der Codemethode (char [] paramArrayofchar, int paramint1, int paramint2) ruft zunächst das Standard -Codierungsformat des Systems auf. Wenn das Codierungsformat nicht angegeben ist, wird die Codierungsoperation standardmäßig mit dem ISO-8859-1 Codierungsformat durchgeführt. Eine weitere Vertiefung ist wie folgt:
String csn = (charSetName == null)? "ISO-8859-1": CharsetName;
In derselben Methode können Sie sehen, dass der Konstruktor der neuen String als StringCoding.decode () -Methode bezeichnet wird:
public string (byte bytes [], int offset, int länge, charset charset) {if (charset == null) werfen neue nullpointerexception ("charset"); CheckBounds (Bytes, Offset, Länge); this.Value = stringCoding.decode (charset, bytes, offset, länge); } Die Dekodemethode und die Encodes verarbeitet das Codierungsformat auf die gleiche Weise.
Für die beiden oben genannten Situationen müssen wir nur ein einheitliches Codierungsformat festlegen, im Allgemeinen werden keine verstümmelten Probleme auftreten.
3.. Codierungs- und Codierungsformat
Schauen Sie sich zunächst das Java -Codierungsklassendiagramm an
Setzen Sie zunächst die Chartset -Klasse gemäß dem angegebenen Diagramm ein, erstellen Sie dann das DiagrammsetEn -Objekt gemäß dem Diagramm und rufen Sie schließlich CharSetEnCoder.Encode auf, um die Zeichenfolge zu codieren. Unterschiedliche Codierungstypen entsprechen einer Klasse, und der tatsächliche Codierungsprozess wird in diesen Klassen abgeschlossen. Das folgende Timing -Diagramm zeigt den detaillierten Codierungsprozess:
Durch dieses codierte Klassendiagramm und das Timing -Diagramm können Sie den detaillierten Codierungsprozess verstehen. Im Folgenden werden ISO-8859-1, GBK und UTF-8 durch einen einfachen Code codiert.
public class test02 {public static void main (String [] args) löst nicht unterstütztenCodingException aus {String string = "Ich bin cm"; Test02.printchart (String.toCharArray ()); Test02.printchart (string.getBytes ("ISO-8859-1")); Test02.printchart (string.getBytes ("gbk")); Test02.printchart (string.getBytes ("utf-8")); } / *** CHAR in hexadezimal konvertieren* / public static void printchart (char [] chars) {for (int i = 0; i <charsgth; Length; i ++) {System.out.print (Integer.ToHexString (chars [i])+"); } System.out.println (""); } / ** * Byte in hex * / public static void printChart (byte [] bytes) {for (int i = 0; i <bytes.length; i ++) {String hex = Integer.tohexString (Bytes [i] & 0xff); if (hex.length () == 1) {hex = '0' + hex; } System.out.print (hex.touppercase () + ""); } System.out.println (""); }}Ausgabe:
6211 662f 20 63 6d 3f 3f 20 63 6d CE D2 Ca C7 20 63 6d E6 88 91 E6 98 AF 20 63 6d
Durch das Programm können wir sehen, dass das Ergebnis von "Ich bin CM" lautet:
char []: 6211 662f 20 63 6d ISO-8859-1: 3f 3f 20 63 6d GBK: CE D2 CA C7 20 63 6D UTF-8: E6 88 91 E6 98 AF 20 63 6d
Das Bild lautet wie folgt: