Heim  >  Artikel  >  Java  >  Teilen von Lösungen für Probleme mit verstümmeltem Code in Java

Teilen von Lösungen für Probleme mit verstümmeltem Code in Java

黄舟
黄舟Original
2017-07-20 14:13:161529Durchsuche

1. Verstümmelte Zeichen aufgrund der Dateiseitenkodierung.

Jede Datei (Java, JS, JSP, HTML usw.) hat ihr eigenes Kodierungsformat. Der Code in der Datei wird normalerweise in einer Kodierung angezeigt, in einer anderen Kodierung jedoch verstümmelt.

In Eclipse verfügt jedes Projekt über ein Kodierungsformat (Textdateikodierung), das im Allgemeinen standardmäßig GBK ist. Eine bessere Programmiergewohnheit besteht darin, ein neues Projekt zu erstellen und zunächst die Projektkodierung auf UTF-8 festzulegen.

Der Grund dafür ist sehr einfach. UTF-8 enthält Zeichen, die alle Länder der Welt verwenden müssen. Es handelt sich um eine internationale Kodierung und eine große Vielseitigkeit. Die Beziehung zwischen mehreren gängigen Zeichensätzen, GBK, GB2312 und UTF-8, ist wie folgt:

GBK ist ein Standard, der nach einer Erweiterung auf Basis des nationalen Standards GB2312 mit GB2312 kompatibel ist. GBK, GB2312 usw. und UTF8 müssen durch Unicode-Codierung ineinander konvertiert werden

2. Verstümmelte Zeichen, die durch die Zeichenfolgenkonvertierung verschiedener Zeichensätze verursacht werden.

Jeder String wird in der zugrunde liegenden Implementierung in einem Byte-Array gespeichert. Wenn unterschiedliche Zeichensätze verwendet werden, ist die Länge des gespeicherten Arrays natürlich unterschiedlich. Wenn Sie zum Dekodieren nicht denselben Zeichensatz verwenden, werden mit Sicherheit verstümmelte Zeichen angezeigt.

Zum Beispiel der folgende Code:

import java.io.UnsupportedEncodingException; 
import java.nio.charset.Charset; 
public class TestCharset { 
  public static void main(String[] args) throws UnsupportedEncodingException {  
    String strChineseString = "中文"; 
    String encoding = System.getProperty("file.encoding"); 
    System.out.println("系统默认的字符集是:" + encoding); 
    System.out.println(strChineseString.getBytes(Charset.forName("GBK")).length); 
    System.out.println(strChineseString.getBytes(Charset.forName("UTF-8")).length); 
    System.out.println(strChineseString.getBytes().length); 
  } 
}

Das Ausgabeergebnis ist:

Java-Code

1 Der Standardzeichensatz des Systems ist: UTF-8

2.4
3.6
4.6

Es ist ersichtlich, dass bei Verwendung der GBK- und UTF-8-Codierung die Länge des erhaltenen Byte-Arrays unterschiedlich ist. Der Grund dafür ist, dass utf-8 3 Bytes zum Codieren von Chinesisch verwendet, während GBK 2 Bytes zum Codieren von Chinesisch verwendet. Da mein Projekt standardmäßig UTF-8 verwendet, ist die Länge des Arrays, das durch die Verwendung von getBytes() ohne Parameter erhalten wird, dieselbe wie die Länge der in UTF-8 codierten Zeichenfolge. Detaillierte Informationen zu Zeichensätzen finden Sie in der im ersten Teil angegebenen Artikeladresse.

Beschreibung der getBytes-Methode im JDK:

getBytes() codiert diesen String mithilfe des Standardzeichensatzes der Plattform in eine Bytesequenz und speichert das Ergebnis in einer neuen Byte-Array-Mitte.

getBytes(Charset charset) Codiert diesen String unter Verwendung des angegebenen Zeichensatzes in eine Bytesequenz und speichert das Ergebnis in einem neuen Byte-Array.

Jeder String hat seine eigene zugrunde liegende Codierung. Sobald jedoch die getByte-Methode aufgerufen wird, ist das erhaltene Byte-Array ein mit einem bestimmten Zeichensatz codiertes Array, und es ist keine unnötige Konvertierung erforderlich.

Nachdem Sie das obige Byte-Array erhalten haben, können Sie eine andere Methode von String aufrufen, um den String zu generieren, der transkodiert werden muss.

Das Testbeispiel lautet wie folgt:

import java.io.UnsupportedEncodingException; 
import java.nio.charset.Charset; 
public class TestCharset { 
  public static void main(String[] args) throws UnsupportedEncodingException { 
    String strChineseString = "中文"; 
    byte[] byteGBK = null; 
    byte[] byteUTF8 = null; 
    byteGBK = strChineseString.getBytes(Charset.forName("GBK")); 
    byteUTF8 = strChineseString.getBytes(Charset.forName("utf-8")); 
    System.out.println(new String(byteGBK,"GBK")); 
    System.out.println(new String(byteGBK,"utf-8")); 
    System.out.println("**************************"); 
    System.out.println(new String(byteUTF8,"utf-8")); 
    System.out.println(new String(byteUTF8,"GBK")); 
  } 
}

Das Ausgabeergebnis ist:

1.中文  
2.����  
3.**************************  
4.中文  
5.涓枃

Es ist ersichtlich, welcher Zeichensatz zum Codieren eines Strings verwendet wird. und beim Generieren eines Strings muss die entsprechende Codierung verwendet werden, sonst werden verstümmelte Zeichen angezeigt.
Um es einfach auszudrücken: Nur String-Transkodierungen, die die folgende Formel erfüllen, werden nicht verstümmelt.

String strSource = "你想要转码的字符串"; 
String strSomeEncoding = "utf-8";  //例如utf-8 
String strTarget = new String (strSource.getBytes(Charset.forName(strSomeEncoding)), strSomeEncoding);

Beschreibung der getBytes-Methode im JDK:

String(byte[] bytes) Konstruiert einen neuen String durch Dekodierung des angegebenen Byte-Arrays mit dem Standardzeichensatz der Plattform.

String(byte[] bytes, Charset charset) Konstruiert einen neuen String durch Dekodierung des angegebenen Byte-Arrays mit dem angegebenen Zeichensatz.

3. Chinesische verstümmelte Zeichen, verursacht durch Socket-Netzwerkübertragung.

Wenn Sie Socket für die Kommunikation verwenden, gibt es viele Optionen für die Übertragung. Sie können PrintStream oder PrintWriter verwenden. Die Übertragung von Englisch ist in Ordnung, die Übertragung von Chinesisch kann jedoch zu verstümmelten Zeichen führen. Es gibt viele Meinungen im Internet. Nach tatsächlichen Tests wurde festgestellt, dass das Problem immer noch in Bytes und Zeichen liegt.

Wie wir alle wissen, ist Java in Byte-Stream und Zeichen-Stream unterteilt. Zeichen (char) sind 16 Bit und Byte (BYTE) ist 8 Bit. PrintStrean schreibt eine Zeichenfolge mit 8-Bit-Daten. PrintWriter schreibt eine Zeichenfolge mit 16-Bit-Daten.

String verwendet standardmäßig die UNICODE-Codierung, also 16 Bit. Daher sind mit PrintWriter geschriebene Zeichenfolgen plattformübergreifend besser, während PrintStream möglicherweise verstümmelte Zeichensätze aufweist.

Sie können die oben genannten Wörter so verstehen, dass PrintStream zum Betreiben von Byte verwendet wird und PrintWriter zum Betreiben von Unicode verwendet wird. Wenn PrintStream auf chinesische Zeichen trifft (ein chinesisches Zeichen belegt 16 Bit). ) werden möglicherweise verstümmelte Zeichen angezeigt. Bei der Verarbeitung von Chinesisch wird im Allgemeinen PrintWriter verwendet.

Beim abschließenden Website-Test gab es mit PrintWriter keinen verstümmelten Code. Der Code lautet wie folgt:

import java.io.BufferedReader; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import java.net.Socket; 
public class TestSocket { 
  public static void main(String[] args) throws IOException { 
    Socket socket = new Socket(); 
    DataOutputStream dos = null; 
    PrintWriter pw = null;    
    BufferedReader in = null; 
    String responseXml = "要传输的中文"; 
    //.......... 
    dos = new DataOutputStream(socket.getOutputStream()); 
    pw = new PrintWriter(new OutputStreamWriter(dos)); //不带自动刷新的Writer      
    pw.println(responseXml); 
    pw.flush(); 
  } 
}

Zu beachten ist, dass Sie println von PrintWriter anstelle der Schreibmethode verwenden müssen, da der Server sonst die Daten nicht lesen kann. Der Grund dafür ist, dass println bei der Ausgabe nach der Zeichenfolge ein Zeilenumbruchzeichen hinzufügt, beim Schreiben jedoch nicht.

4. Chinesische verstümmelte Zeichen werden in JSP angezeigt.

Manchmal weist die JSP-Seite bei der Anzeige von Chinesisch verstümmelte Zeichen auf. In den meisten Fällen liegt ein Problem mit der Zeichensatzkonfiguration und der Seitenkodierung vor. Solange es bei den folgenden Konfigurationen keine Probleme gibt, treten im Allgemeinen keine verstümmelten Zeichen auf.

a. Fügen Sie die folgende Anweisung oben auf der JSP-Seite hinzu:

<%@ page contentType="text/html; charset=utf-8" language="java" errorPage="" %>

b. Fügen Sie die folgende Anweisung im Head-Tag von HTML hinzu.

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

c. Stellen Sie sicher, dass die Seitenkodierung von JSP mit dem Zeichensatz der beiden oben genannten übereinstimmt.

上面的字符集可以根据需要自己灵活选择,不一定非要utf-8。不过因为utf-8对各国语言,特别是中文支持较好,所以推荐使用。我就曾经遇到过滘在GB2312编码的页面无法正常显示的问题。

5.Post和Get传递中文,后台获取乱码。

前台传递中文也分为Get和Post方法。

a.Get方法的情况:

Get方法的时候主要是URL传递中文。

如果是在js文件中,可以使用如下代码进行中文转码。

var url ="http://www.baidu.com/s?industry=编码"
url = encodeURI(url);

如果是在jsp文件中,则可以使用如下语句进行转码。
页面开始引入:

<%@ page import="java.net.URLEncoder" %>

      需要转码的地方使用URLEncoder进行编码:

<a href="xxxxx.xx?industry=<%=URLEncoder.encode(" rel="external nofollow" http://www.baidu.com/s?wd=编码", "UTF-8")%>">

无论使用哪种方法,在后台获取中文的时候都要使用如下代码:

request.setCharacterEncoding("utf-8"); 
String industry = new String( 
request.getParameter("industry ").getBytes("ISO8859-1"),"UTF-8");

【注】

1.对于request,是指提交内容的编码,指定后可以通过getParameter()则直接获得正确的字符串,如果不指定,则默认使用iso8859-1编码,为了统一,需要提交指定传输编码。

2.上面代码的第二句好像和第2条中给出的公式矛盾。我也纠结了好久,最后发现ISO8859-1是一种比较老的编码,通常叫做Latin-1,属于单字节编码,正好和计算机最基础的表示单位一致,因此使用它进行转码一般也没有问题。

iso-8859-1是JAVA网络传输使用的标准字符集,而gb2312是标准中文字符集,当你作出提交表单等需要网络传输的操作的时候,就需要把 iso-8859-1转换为gb2312字符集显示,否则如果按浏览器的gb2312格式来解释iso-8859-1字符集的话,由于2者不兼容,所以会是乱码。为了省事,建议统一使用utf-8字符集。
b.POST方法的情况。 

对于Post的情况就比较简单了,只需要在post的函数调用部分,制定post的header的字符集,如:

xmlHttp.open("post", url , true); 
xmlHttp.setRequestHeader("Content-Type","text/xml; charset= utf-8");  
xmlHttp.send(param);

其中param为要传递的参数。

后台部分和get方法一样,设置如下即可,注意传输和接受的字符集要统一。

 6.后台向前台传递中文乱码。

在这里提供一个函数,通过这个函数来发送信息,就不会出现乱码,核心思想也是设置response流的字符集。函数代码如下:

/** 
 * @Function:writeResponse 
 * @Description:ajax方式返回字符串 
 * @param str:json 
 * @return:true:输出成功,false:输出失败 
 */
public boolean writeResponse(String str){ 
  boolean ret = true; 
  try{ 
    HttpServletResponse response = ServletActionContext.getResponse(); 
    response.setContentType("text/html;charset=utf-8"); 
    PrintWriter pw = response.getWriter(); 
    pw.print(str); 
    pw.close(); 
  }catch (Exception e) { 
    ret = false; 
    e.printStackTrace(); 
  } 
  return ret; 
}

7.下载文件时文件名乱码。

下过下载的人都知道下载的文件容易出现乱码,原因也是没有对输出流的编码格式进行限定。

附上一段代码,用来帮你完成无乱码下载。

Java代码  

HttpServletResponse response = ServletActionContext.getResponse(); 
response.setContentType("text/html;charset=utf-8"); 
response.reset(); 
String header = "attachment; filename=" + picName; 
   header = new String(header.getBytes(), "UTF-8"); 
   response.setHeader("Content-disposition", header);

核心代码就上几句,注意第二句和第三句的reset的顺序不能搞错。

reset的作用是用来清空buffer缓存的,清空请求前部的一些空白行。 

Das obige ist der detaillierte Inhalt vonTeilen von Lösungen für Probleme mit verstümmeltem Code in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn