>  기사  >  Java  >  Java의 잘못된 코드 문제에 대한 솔루션 공유

Java의 잘못된 코드 문제에 대한 솔루션 공유

黄舟
黄舟원래의
2017-07-20 14:13:161487검색

1. 파일 페이지 인코딩으로 인해 문자가 깨졌습니다.

각 파일(java, js, jsp, html 등)에는 고유한 인코딩 형식이 있습니다. 파일의 코드는 한 인코딩에서는 정상적으로 표시되지만 다른 인코딩에서는 왜곡되어 나타납니다.

Eclipse에서 각 프로젝트에는 일반적으로 GBK가 기본값인 인코딩 형식(텍스트 파일 인코딩)이 있습니다. 더 나은 프로그래밍 습관은 새 프로젝트를 만들고 먼저 프로젝트 인코딩을 UTF-8로 설정하는 것입니다.

그 이유는 매우 간단합니다. UTF-8은 전 세계 모든 국가에서 사용해야 하는 문자를 포함하고 있으며 강력한 다양성을 가지고 있습니다. 여러 공통 문자 세트인 GBK, GB2312 및 UTF-8 간의 관계는 다음과 같습니다.

GBK는 국가 표준 GB2312를 기반으로 확장 후 GB2312와 호환되는 표준입니다. GBK, GB2312 등과 UTF8은 유니코드 인코딩을 통해 서로 변환되어야 합니다

2. 서로 다른 문자 집합의 문자열 변환으로 인해 문자가 깨졌습니다.

모든 문자열은 기본 구현에서 바이트 배열에 저장됩니다. 다른 문자 집합이 사용되는 경우 저장된 배열의 길이는 물론 달라집니다. 디코딩에 동일한 문자 세트를 사용하지 않으면 분명히 잘못된 문자가 나타날 것입니다.

예를 들어 다음 코드는

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

출력 결과는

Java 코드

1입니다. 시스템 기본 문자 집합은 UTF-8

2.4
3.6
4.6

GBK와 UTF-8 인코딩을 사용하면 결과 바이트 배열의 길이가 다릅니다. 그 이유는 utf-8은 중국어를 인코딩하는 데 3바이트를 사용하고 GBK는 중국어를 인코딩하는 데 2바이트를 사용하기 때문입니다. 내 프로젝트는 기본적으로 UTF-8을 사용하기 때문에 매개 변수 없이 getBytes()를 사용하여 얻은 배열의 길이는 UTF-8로 인코딩된 문자열의 길이와 동일합니다. 문자 집합에 대한 자세한 내용은 첫 번째 부분에 제공된 기사 주소를 참조하세요.

JDK의 getBytes 메소드 설명:

getBytes()는 플랫폼의 기본 문자 세트를 사용하여 이 문자열을 바이트 시퀀스로 인코딩하고 결과를 새 바이트 배열에 저장합니다.

getBytes(Charset charset) 주어진 문자 세트를 사용하여 이 문자열을 바이트 시퀀스로 인코딩하고 결과를 새 바이트 배열에 저장합니다.

각 문자열 하단에는 고유한 인코딩 방법이 있습니다. 그러나 getByte 메소드가 호출되면 획득된 바이트 배열은 특정 문자 세트를 사용하여 인코딩된 배열이므로 불필요한 변환이 필요하지 않습니다.

위의 바이트 배열을 얻은 후 String의 다른 메서드를 호출하여 트랜스코딩해야 하는 문자열을 생성할 수 있습니다.

테스트 예는 다음과 같습니다.

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

출력 결과는 다음과 같습니다.

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

문자열을 인코딩하는 데 어떤 문자 집합이 사용되는지 알 수 있으며, 문자열을 생성할 때 해당 인코딩을 사용해야 합니다. 그렇지 않으면 잘못된 문자가 표시됩니다. 나타나다.
간단히 말하면, 다음 수식을 만족하는 문자열 트랜스코딩만 깨지지 않습니다.

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

JDK의 getBytes 메소드 설명:

String(byte[] bytes) 플랫폼의 기본 문자 세트를 사용하여 지정된 바이트 배열을 디코딩하여 새 문자열을 구성합니다.

String(byte[] bytes, Charset charset) 지정된 문자 세트를 사용하여 지정된 바이트 배열을 디코딩하여 새 문자열을 구성합니다.

3. 소켓 네트워크 전송으로 인해 중국어 문자가 깨졌습니다.

소켓을 통신에 사용하는 경우에는 PrintStream 또는 PrintWriter를 사용할 수 있습니다. 영어를 전송하는 것은 괜찮지만, 중국어를 전송하면 문자가 깨질 수 있습니다. 실제 테스트를 해본 결과 여전히 바이트와 문자에 문제가 있다는 의견이 인터넷에 많이 떠돌고 있습니다.

우리 모두 알다시피 Java는 바이트 스트림과 문자 스트림으로 구분됩니다. 문자(char)는 16비트이고 바이트(BYTE)는 8비트입니다. PrintStrean은 8비트 데이터 문자열을 씁니다. PrintWriter는 16비트 데이터 문자열을 씁니다.

String은 기본적으로 16비트 UNICODE 인코딩을 사용합니다. 따라서 PrintWriter로 작성된 문자열은 크로스 플랫폼에 더 적합하지만 PrintStream은 잘못된 문자 집합을 가질 수 있습니다.

위의 말은 이렇게 이해할 수 있습니다. PrintStream은 바이트를 연산하는 데 사용되며, PrintWriter는 유니코드를 연산하는 데 사용됩니다. PrintStream이 한 번에 8비트를 읽는 경우 한자(한자 1개가 16비트를 차지함)를 만나면 문자가 깨집니다. 나타날 수 있습니다. 일반적으로 중국어를 처리할 때에는 PrintWriter를 사용합니다.

최종 웹사이트 테스트에서 PrintWriter를 사용할 때 깨진 문자가 나타나지 않았습니다. 코드는 다음과 같습니다.

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

한 가지 주의할 점은 write 메소드 대신 PrintWriter의 println을 사용해야 한다는 것입니다. 그렇지 않으면 서버가 데이터를 읽을 수 없습니다. 그 이유는 println은 출력할 때 문자열 뒤에 개행 문자를 추가하지만 write는 그렇지 않기 때문입니다.

4. JSP에서 중국어 문자가 깨져 표시됩니다.

JSP 페이지에서 중국어를 표시할 때 문자가 깨질 때가 있습니다. 대부분의 경우 문자 세트 구성 및 페이지 인코딩에 문제가 있습니다. 다음 구성에 문제가 없다면 일반적으로 문자가 깨지는 일이 없습니다.

a. JSP 페이지 상단에 다음 문을 추가합니다.

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

b HTML의 head 태그에 다음 문을 추가합니다.

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

c. JSP 페이지 인코딩이 위의 두 문자 세트와 동일한지 확인하세요.

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

위 내용은 Java의 잘못된 코드 문제에 대한 솔루션 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.