Maison  >  Article  >  Java  >  Partager des solutions aux problèmes de code tronqué en Java

Partager des solutions aux problèmes de code tronqué en Java

黄舟
黄舟original
2017-07-20 14:13:161557parcourir

1. Caractères tronqués causés par l'encodage de la page du fichier.

Chaque fichier (java, js, jsp, html, etc.) a son propre format d'encodage. Le code du fichier s'affiche normalement dans un encodage, mais apparaîtra tronqué dans un autre encodage.

Dans Eclipse, chaque projet aura un format d'encodage (encodage de fichier texte), qui est généralement par défaut GBK. Une meilleure habitude de programmation consiste à créer un nouveau projet et à définir d'abord l'encodage du projet sur UTF-8.

La raison en est très simple. UTF-8 contient des caractères que tous les pays du monde doivent utiliser. Il s'agit d'un encodage international et doté d'une grande polyvalence. La relation entre plusieurs jeux de caractères courants, GBK, GB2312 et UTF-8 est la suivante :

GBK est une norme compatible avec GB2312 après extension basée sur la norme nationale GB2312. GBK, GB2312, etc. et UTF8 doivent être convertis entre eux via le codage Unicode

2. Caractères tronqués causés par la conversion de chaînes de différents jeux de caractères.

Chaque chaîne est stockée dans un tableau d'octets dans l'implémentation sous-jacente. Si différents jeux de caractères sont utilisés, la longueur du tableau stocké sera bien sûr différente. Si vous n'utilisez pas le même jeu de caractères pour le décodage, des caractères tronqués apparaîtront certainement.

Par exemple, le code suivant :

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); 
  } 
}

Le résultat de sortie est :

Code Java

1. Le jeu de caractères par défaut du système est : UTF-8

2.4
3.6
4.6

On peut voir qu'en utilisant l'encodage GBK et UTF-8, la longueur du tableau d'octets obtenu est différente. La raison en est que utf-8 utilise 3 octets pour coder le chinois, tandis que GBK utilise 2 octets pour coder le chinois. Étant donné que mon projet utilise UTF-8 par défaut, la longueur du tableau obtenu en utilisant getBytes() sans paramètres est la même que la longueur de la chaîne codée en UTF-8. Pour des connaissances détaillées sur les jeux de caractères, veuillez vous référer à l'adresse de l'article indiquée dans la première partie.

Description de la méthode getBytes dans JDK :

getBytes() encode cette chaîne dans une séquence d'octets en utilisant le jeu de caractères par défaut de la plateforme et stocke le résultat dans un nouveau milieu de tableau d'octets.

getBytes(Charset charset) Encode cette chaîne dans une séquence d'octets en utilisant le jeu de caractères donné et stocke le résultat dans un nouveau tableau d'octets.

Chaque chaîne a son propre encodage sous-jacent. Cependant, une fois la méthode getByte appelée, le tableau d'octets obtenu est un tableau codé avec un jeu de caractères spécifique et aucune conversion redondante n'est requise.

Après avoir obtenu le tableau d'octets ci-dessus, vous pouvez appeler une autre méthode de String pour générer la chaîne qui doit être transcodée.

L'exemple de test est le suivant :

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")); 
  } 
}

Le résultat de sortie est :

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

On peut voir quel jeu de caractères est utilisé pour encoder une chaîne, et lors de la génération d'une chaîne, l'encodage correspondant doit être utilisé, sinon des caractères tronqués apparaîtront.
Pour faire simple, seul le transcodage de chaînes qui satisfait à la formule suivante ne sera pas tronqué.

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

Description de la méthode getBytes dans JDK :

String(byte[] bytes) Construit une nouvelle chaîne en décodant le tableau d'octets spécifié en utilisant le jeu de caractères par défaut de la plateforme.

String(byte[] bytes, Charset charset) Construit une nouvelle chaîne en décodant le tableau d'octets spécifié à l'aide du jeu de caractères spécifié.

3. Caractères chinois tronqués causés par la transmission réseau Socket.

Lorsque vous utilisez Socket pour la communication, il existe de nombreuses options de transmission. Vous pouvez utiliser PrintStream ou PrintWriter. La transmission de l'anglais est acceptable, mais la transmission du chinois peut entraîner des caractères tronqués. Il existe de nombreuses opinions sur Internet. Après des tests réels, il a été constaté que le problème réside toujours dans les octets et les caractères.

Comme nous le savons tous, Java est divisé en flux d'octets et flux de caractères. Le caractère (char) est de 16 bits et l'octet (BYTE) est de 8 bits. PrintStrean écrit une chaîne de données de 8 bits. PrintWriter écrit une chaîne de données de 16 bits.

String utilise le codage UNICODE par défaut, qui est de 16 bits. Par conséquent, les chaînes écrites avec PrintWriter sont meilleures sur plusieurs plates-formes, tandis que PrintStream peut avoir des jeux de caractères tronqués.

Vous pouvez comprendre les mots ci-dessus comme ceci. PrintStream est utilisé pour faire fonctionner l'octet, PrintWriter est utilisé pour faire fonctionner Unicode. Si PrintStream lit 8 bits à la fois, s'il rencontre des caractères chinois (un caractère chinois occupe 16 bits). ), des caractères tronqués peuvent apparaître. Généralement, PrintWriter est utilisé lors du traitement du chinois.

Lors du test final du site Web, il n'y avait aucun code tronqué utilisant PrintWriter. Le code est le suivant :

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(); 
  } 
}

Une chose à noter est que vous devez utiliser le println de PrintWriter au lieu de la méthode write, sinon le serveur ne pourra pas lire les données. La raison est que println ajoutera un caractère de nouvelle ligne après la chaîne lors de la sortie, mais pas write.

4. Les caractères chinois tronqués sont affichés dans JSP.

Parfois, la page JSP aura des caractères tronqués lors de l'affichage du chinois. Dans la plupart des cas, il s'agit d'un problème avec la configuration du jeu de caractères et l'encodage de la page. Tant qu'il n'y a aucun problème avec les configurations suivantes, il n'y aura généralement pas de caractères tronqués.

a. Ajoutez l'instruction suivante en haut de la page JSP :

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

b. Ajoutez l'instruction suivante dans la balise head du HTML.

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

c. Assurez-vous que l'encodage de la page JSP est le même que le jeu de caractères des deux ci-dessus.

上面的字符集可以根据需要自己灵活选择,不一定非要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缓存的,清空请求前部的一些空白行。 

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn