1. Proses konversi pengkodean java
Kami selalu menggunakan file kelas Java untuk berinteraksi dengan pengguna yang paling langsung (input, output), dan teks yang terkandung dalam konten interaktif ini mungkin berisi Cina. Apakah kelas Java ini berinteraksi dengan database atau dengan halaman front-end, siklus hidup mereka selalu seperti ini:
(1) Pemrogram menulis kode program melalui editor pada sistem operasi dan menyimpan sistem operasi dalam format .java. Kami memanggil file -file ini file sumber.
(2) Kompilasi file sumber ini melalui javac.exe di JDK untuk membentuk kelas .class.
(3) Jalankan kelas -kelas ini secara langsung atau sebutkan di wadah web untuk mendapatkan hasil output.
Proses -proses ini diamati dari perspektif makro, dan jelas tidak mungkin untuk memahami hal ini. Kita perlu benar -benar memahami bagaimana Java dikodekan dan diterjemahkan:
Langkah 1: Ketika kami menggunakan editor untuk menulis file sumber Java, file program akan menggunakan format penyandian default dari sistem operasi (biasanya sistem operasi Cina kami menggunakan format penyandian GBK) untuk membentuk file .java. File Sumber Java disimpan dalam format pengkodean pengkodean file.encoding yang didukung oleh sistem operasi secara default. Kode berikut dapat melihat nilai sistem parameter file.encoding sistem.
System.out.println (System.GetProperty ("File.encoding")); Langkah 2: Ketika kami menggunakan javac.exe untuk mengkompilasi file Java kami, JDK pertama -tama akan mengkonfirmasi pengkodean parameter kompilasi untuk menentukan set karakter kode sumber. Jika kami tidak menentukan parameter kompilasi, JDK pertama -tama akan mendapatkan parameter file default sistem operasi, dan kemudian JDK akan mengonversi program sumber Java yang kami tulis dari format pengkodean file.
Langkah 3: JDK menulis informasi yang dikompilasi dan disimpan pada memori di atas ke dalam file kelas untuk membentuk file .class. Pada saat ini, file .class dikodekan unicode, yang berarti bahwa konten dalam file .class umum kami dikonversi ke format pengkodean unicode, apakah mereka karakter Cina atau bahasa Inggris.
Pada langkah ini, metode penanganan file sumber JSP sedikit berbeda: wadah web memanggil kompiler JSP. Kompiler JSP akan terlebih dahulu memeriksa apakah file JSP memiliki format pengkodean file. Jika tidak diatur, kompiler JSP akan menghubungi JDK untuk mengubah file JSP menjadi kelas servlet sementara menggunakan metode pengkodean default, dan kemudian mengkompilasinya menjadi file .class dan menyimpannya di folder sementara.
Langkah 4: Jalankan kelas yang dikompilasi: akan ada beberapa situasi di sini
(1) Jalankan langsung di konsol.
(2) Kelas JSP/Servlet.
(3) antara kelas Java dan database.
Masing -masing dari tiga situasi ini akan memiliki cara berbeda untuk melakukannya.
1. Kelas berjalan di konsol
Dalam hal ini, JVM pertama -tama akan membaca file kelas yang disimpan dalam sistem operasi ke dalam memori. Pada saat ini, file kelas dalam memori dikodekan dalam Unicode, dan kemudian JVM akan menjalankannya. Jika pengguna perlu memasukkan informasi, input informasi oleh pengguna akan dikodekan dalam format file.encoding dan dikonversi ke format pengkodean unicode untuk menyimpannya dalam memori. Setelah program dijalankan, hasilnya dikonversi menjadi format file.encoding dan dikembalikan ke sistem operasi dan output ke antarmuka. Seluruh proses adalah sebagai berikut:
Pada seluruh proses di atas, tidak ada kesalahan yang dapat terjadi dalam konversi pengkodean apa pun yang terlibat, jika tidak kode kacau akan terjadi.
2. Kelas SERVLET
Karena file JSP pada akhirnya akan dikonversi menjadi file servlet (tetapi lokasi penyimpanan berbeda), kami juga akan menyertakan file JSP di sini.
Ketika pengguna meminta servlet, wadah web memanggil JVM untuk menjalankan servlet. Pertama -tama, JVM akan memuat kelas servlet ke dalam memori. Kode servlet dalam memori dalam format pengkodean unicode. Kemudian JVM menjalankan servlet dalam memori. Selama menjalankan, jika Anda perlu menerima data yang ditularkan dari klien (seperti data yang disahkan oleh formulir dan URL), wadah web akan menerima data yang masuk. Selama proses penerimaan, jika program menetapkan pengkodean parameter yang masuk, format pengkodean set diadopsi. Jika tidak diatur, format pengkodean ISO-8859-1 default diadopsi. Setelah data yang diterima, JVM akan mengubah format pengkodean menjadi Unicode dan menyimpannya dalam memori. Setelah menjalankan servlet, hasil output dihasilkan, dan format pengkodean hasil output ini masih unicode. Segera setelah itu, wadah web akan langsung mengirim string format pengkodean UNICODE yang dihasilkan ke klien. Jika program menentukan format pengkodean pada saat output, itu akan menjadi output ke browser sesuai dengan format pengkodean yang ditentukan. Jika tidak, format pengkodean ISO-8859-1 default diadopsi. Seluruh bagan aliran proses adalah sebagai berikut:
3. Bagian Basis Data
Kita tahu bahwa koneksi antara program Java dan basis data terhubung melalui driver JDBC, dan driver JDBC default ke format pengkodean ISO-8859-1. Dengan kata lain, ketika kita meneruskan data ke database melalui program Java, JDBC akan terlebih dahulu mengonversi data dalam format pengkodean unicode menjadi format pengkodean ISO-8859-1, dan kemudian menyimpannya dalam database, yaitu, ketika database menyimpan data, format default adalah ISO-8859-1.
2. Pengkodean & Decoding
Berikut ini akan mengakhiri operasi pengkodean dan decoding yang perlu dilakukan Java dalam kesempatan itu, dan memilah proses perantara secara rinci untuk lebih menguasai proses pengkodean dan decoding Java. Ada empat skenario utama di Java yang membutuhkan pengkodean dan decoding:
(1): Operasi I/O.
(2): memori
(3): Database
(4): Javaweb
Berikut ini terutama memperkenalkan dua skenario sebelumnya. Selama bagian basis data diatur dengan benar, tidak akan ada masalah. Ada terlalu banyak skenario Javaweb dan Anda perlu memahami pengkodean URL, GET, POST, dan DECODING SERVLET, sehingga pengenalan LZ dari skenario Javaweb.
1. Operasi saya
Dalam LZ sebelumnya menyebutkan bahwa masalah kacau tidak lebih dari ketidakkonsistenan format pengkodean selama proses transkoding. Misalnya, UTF-8 digunakan untuk pengkodean dan GBK digunakan untuk decoding. Namun, alasan yang paling mendasar adalah bahwa ada masalah dengan konversi karakter-ke-byte atau byte-to-karakter, dan skenario utama konversi dalam kasus ini adalah operasi I/O. Tentu saja, operasi I/O terutama termasuk jaringan I/O (yaitu, Javaweb) dan Disk I/O. Jaringan I/O diperkenalkan di bagian selanjutnya.
Pertama, mari kita lihat operasi pengkodean I/O.
InputStream adalah superclass dari semua kelas aliran input byte, dan pembaca adalah kelas abstrak pembaca. Java membaca file dengan cara yang dibagi menjadi aliran byte dan dengan aliran karakter. Inputstream dan pembaca adalah superclass dari dua metode membaca ini.
Dengan byte, kami biasanya menggunakan metode inputStream.read () untuk membaca byte dalam aliran data (baca () hanya membaca satu byte pada satu waktu, yang sangat lambat. Kami biasanya menggunakan baca (byte [])), kemudian simpan dalam array byte [], dan akhirnya mengonversi menjadi string. Ketika kita membaca file, pengkodean byte tergantung pada format pengkodean yang digunakan oleh file, dan masalah pengkodean juga akan terlibat dalam konversi ke proses string. Jika format pengkodean berbeda antara keduanya, masalahnya dapat terjadi. Misalnya, ada masalah yang format pengkodean test.txt adalah UTF-8, sehingga format pengkodean aliran data yang diperoleh saat membaca file melalui aliran byte adalah UTF-8. Jika kami tidak menentukan format pengkodean selama konversi ke string, kami menggunakan sistem pengkodean sistem (GBK) secara default ke decoding. Karena format pengkodean keduanya tidak konsisten, maka kode yang kacau pasti akan terjadi dalam proses membangun string, sebagai berikut:
File file = file baru ("c: //test.txt"); InputStream input = new FileInputStream (file); StringBuffer buffer = stringBuffer baru (); byte [] bytes = byte baru [1024]; untuk (int n; (n = input.read (bytes))! =-1;) {buffer.append (string baru (bytes, 0, n)); } System.out.println (buffer); Hasil output kacau ...
Konten di test.txt adalah: saya cm.
Untuk menghindari kode yang kacau, tentukan format pengkodean selama proses konstruksi string sehingga format pengkodean keduanya konsisten selama pengkodean dan decoding:
buffer.append (string baru (bytes, 0, n, "UTF-8"));
Dengan karakter, aliran karakter dapat dianggap sebagai aliran pembungkus. Lapisan yang mendasarinya masih menggunakan aliran byte untuk membaca byte, dan kemudian memecahkan kode byte baca menjadi karakter menggunakan metode pengkodean yang ditentukan. Di Java, Reader adalah superclass yang membaca aliran karakter. Jadi dari perspektif bawah, tidak ada perbedaan antara membaca file dengan byte dan membaca berdasarkan karakter. Saat membaca, membaca karakter dibiarkan dengan byte setiap kali, dan aliran byte membaca satu byte pada satu waktu.
BYTE & KONVERSI KARAKTER Konversi byte menjadi karakter pada dasarnya adalah inputStreamReader. API dijelaskan sebagai berikut: InputStreamReader adalah jembatan antara aliran byte ke aliran karakter: ia membaca byte menggunakan charset yang ditentukan dan mendekodenya menjadi karakter. Set karakter yang digunakannya dapat ditentukan atau secara eksplisit diberikan dengan nama, atau dapat menerima set karakter default platform. Setiap panggilan ke metode baca () dalam inputStreamReader menghasilkan satu atau lebih byte yang dibaca dari aliran input yang mendasarinya. Untuk mengaktifkan konversi yang efektif dari byte ke karakter, Anda dapat membaca lebih banyak byte dari aliran yang mendasarinya sebelumnya, melebihi byte yang diperlukan untuk memenuhi operasi baca saat ini. Penjelasan API sangat jelas. InputStreamReader masih menggunakan pembacaan byte saat membaca file di bagian bawah. Setelah membaca byte, perlu menguraikan karakter sesuai dengan format pengkodean yang ditentukan. Jika tidak ada format pengkodean yang ditentukan, ia mengadopsi format pengkodean default sistem.
String file = "c: //test.txt"; String charset = "UTF-8"; // Tulis karakter untuk dikonversi ke byte stream fileOutputStream outputStream = new FileOutputStream (file); OutputStreamWriter writer = outputStreamWriter baru (outputStream, charset); coba {writer.write ("I Am CM"); } akhirnya {writer.close (); } // Baca byte untuk mengonversi ke karakter fileInputStream inputStream = new fileInputStream (file); InputStreamReader reader = inputStreamReader baru (inputStream, charset); StringBuffer buffer = stringBuffer baru (); char [] buf = char baru [64]; Int Count = 0; coba {while ((count = reader.read (buf))! = -1) {buffer.append (buf, 0, count); }} akhirnya {reader.close (); } System.out.println (buffer); 2. Memori
Pertama, mari kita lihat kode sederhana berikut
String S = "I Am CM"; byte [] bytes = s.getbytes (); String s1 = string baru (bytes, "gbk"); String s2 = string baru (bytes);
Dalam kode ini kita melihat tiga proses konversi pengkodean (satu pengkodean, dua decoding). Mari kita lihat string.gettytes () pertama:
byte publik [] getBytes () {return stringcoding.encode (value, 0, value.length); }Hubungi secara internal metode stringcoding.encode ():
static byte [] encode (char [] ca, int off, int len) {string csn = charset.defaultCharset (). name (); Coba {// Gunakan varian nama charset encode () yang menyediakan caching. return encode (CSN, CA, Off, Len); } catch (UnsupportedencodingException x) {warnunsupportedcharset (CSN); } coba {return encode ("iso-8859-1", ca, off, len); } catch (UnsupportedEncodingException x) {// Jika kode ini terkena selama inisialisasi VM, Messageutils adalah // satu -satunya cara kita akan bisa mendapatkan pesan kesalahan apa pun. Messageutils.err ("ISO-8859-1 Charset tidak tersedia:" + x.tostring ()); // Jika kita tidak dapat menemukan ISO-8859-1 (penyandian yang diperlukan) maka hal-hal // benar-benar salah dengan instalasi. System.exit (1); kembali nol; }}Metode Encode (char [] paramArrayofChar, int paramInt1, int paramInt2) pertama memanggil format pengkodean default sistem. Jika format pengkodean tidak ditentukan, operasi pengkodean dilakukan secara default menggunakan format pengkodean ISO-8859-1. Pendalaman lebih lanjut adalah sebagai berikut:
String csn = (charsetName == null)? "ISO-8859-1": CharsetName;
Dalam metode yang sama, Anda dapat melihat bahwa konstruktor string baru disebut metode stringcoding.decode ():
string publik (byte bytes [], int offset, int int, charset charset) {if (charset == null) melempar nullpointerException baru ("charset"); checkbounds (byte, offset, panjang); this.value = StringCoding.decode (charset, byte, offset, length); } Metode decode dan encode menangani format pengkodean dengan cara yang sama.
Untuk dua situasi di atas, kita hanya perlu mengatur format penyandian terpadu, umumnya tidak akan ada masalah yang kacau.
3. Format Pengkodean & Pengkodean
Pertama, lihat diagram kelas pengkodean Java
Pertama, atur kelas chartset sesuai dengan bagan yang ditentukan, kemudian buat objek chartsetencoder sesuai dengan chartSet, dan akhirnya panggil charsetencoder.encode untuk mengkodekan string. Jenis pengkodean yang berbeda akan sesuai dengan kelas, dan proses pengkodean aktual diselesaikan di kelas -kelas ini. Diagram waktu berikut menunjukkan proses penyandian yang terperinci:
Melalui diagram kelas kode dan diagram waktu ini, Anda dapat memahami proses penyandian yang terperinci. Berikut ini akan mengkodekan ISO-8859-1, GBK, dan UTF-8 melalui kode sederhana.
test kelas publik02 {public static void main (string [] args) melempar UnsupportedEncodingException {string string = "I Am CM"; Test02.printchart (string.tochararray ()); Test02.printchart (string.getbytes ("iso-8859-1")); Test02.printchart (string.getbytes ("gbk")); Test02.printchart (string.getBytes ("UTF-8")); } / *** Konversi char ke hexadecimal* / public static void printchart (char [] chars) {for (int i = 0; i <chars.length; i ++) {System.out.print (integer.tohexstring (chars [i])+""); } System.out.println (""); } / ** * byte dikonversi menjadi 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 (""); }}Keluaran:
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
Melalui program ini kita dapat melihat bahwa hasil "I Am CM" adalah:
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
Gambarnya adalah sebagai berikut: