国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java亂碼問題解決方法_動力節點Java學院整理

Java亂碼問題解決方法_動力節點Java學院整理

2020-12-04 09:02動力節點 Java教程

開發java應用出現亂碼是很常見的,畢竟現在unicode的使用還不是很廣泛,下面給大家分享Java亂碼問題解決方法,感興趣的朋友一起看看吧

1.文件頁面編碼導致的亂碼

每一個文件(java,js,jsp,html等)都有其本身的編碼格式,文件中的代碼在一種編碼中顯示正常,在另外一種編碼下就會顯示出亂碼。

在Eclipse中,每一個工程都會有編碼格式(Text file encoding), 一般默認為GBK。而一個比較好的編程習慣是新建一個項目,優先把項目的編碼設為UTF-8。

這樣做的原因很簡單,UTF-8包含全世界所有國家需要用到的字符,是國際編碼,通用性強。幾種常見的字符集,GBK,GB2312,UTF-8之間的關系如下:

GBK是國家標準GB2312基礎上擴容后兼容GB2312的標準。GBK、GB2312等與UTF8之間都必須通過Unicode編碼才能相互轉換

2.不同字符集的字符串轉換時導致的亂碼。

每一個String,底層實現都是用一個byte數組存儲,使用不同的字符集,存儲的數組長度當然就不同。如果不使用同一種字符集進行解碼,就一定會出現亂碼。

例如如下代碼:

Java代碼  

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
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編碼,得到的byte數組長度不一樣,原因就是utf-8使用3個字節來編碼中文,而GBK使用2個字節來編碼中文。因為我的項目默認使用UTF-8,所以使用不加參數的getBytes()得到的數組長度和使用UTF-8編碼的 字符串長度一樣。關于字符集的詳細知識可以參考第一部分中給出的文章地址。

 JDK中關于getBytes方法的描述:

 getBytes() 使用平臺的默認字符集將此 String 編碼為 byte 序列,并將結果存儲到一個新的 byte 數組中。

 getBytes(Charset charset) 使用給定的 charset 將此 String 編碼到 byte 序列,并將結果存儲到新的 byte 數組。

每一個字符串底層都有自己的編碼方式。不過一旦調用getByte方法后,得到的byte數組就是使用某種特定字符集編碼后的數組,不需要再做多余的轉換。

當得到上面的byte數組后,就可以調用String的另外一個方法來生成需要轉碼的String了。

測試例子如下:

Java代碼  

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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"));
  }
}

輸出結果為:

Java代碼  

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

可以看出,使用哪種字符集編碼一個String,在生成一個String的時候就必須使用相應的編碼,否則就會出現亂碼。
簡單來講,只有滿足如下公式的String轉碼,才不會亂碼。

Java代碼  

 
?
1
 
2
3
String strSource = "你想要轉碼的字符串";
String strSomeEncoding = "utf-8"//例如utf-8
String strTarget = new String (strSource.getBytes(Charset.forName(strSomeEncoding)), strSomeEncoding);

JDK中關于getBytes方法的描述:

String(byte[] bytes)  通過使用平臺的默認字符集解碼指定的 byte 數組,構造一個新的 String。 

String(byte[] bytes, Charset charset)  通過使用指定的 charset 解碼指定的 byte 數組,構造一個新的 String。 

3.Socket網絡傳輸時導致的中文亂碼。

使用Socket進行通訊的時候,傳輸有多種選擇,可以使用PrintStream,也可以使用PrintWriter。傳輸英文還好,傳輸中文就可能出現亂碼問題。網上的說法很多,經過實際測試,發現問題還在字節和字符的問題上面。

眾所周知,Java中分為字節流和字符流,字符(char)是16bit的,字節(BYTE)是8bit的。PrintStrean是寫入一串8bit的數據的。 PrintWriter是寫入一串16bit的數據的。 

String缺省是用UNICODE編碼,是16bit的。因此用PrintWriter寫入的字符串,跨平臺性好一些,PrintStream的可能會出現字符集亂碼。

可以這樣理解上面的話,PrintStream是用來操作byte, PrintWriter是用來操作Unicode, PrintStream一次讀8bit的話,如果遇到漢字(一個漢字占16bit),就可能會出現亂碼。一般需要處理中文時用PrintWriter好了。

最后網站測試,使用PrintWriter沒有出現亂碼。代碼如下:

Java代碼  

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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();
  }
}

需要注意的方面是,需要使用PrintWriter的println而不是write方法,否則服務器端會讀不到數據的。原因就是println會在輸出的時候在字符串后面加一個換行符,而write不會。 

4.JSP中顯示中文的亂碼。

有的時候JSP頁面在顯示中文的時候會有亂碼,大多數情況就是字符集配置和頁面編碼的問題。只要保證如下的幾個配置沒有問題,一般就不會有亂碼出現。

a.JSP頁面頂端添加如下語句:

Java代碼  

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

b.在HTML的head標簽中添加如下語句。

Java代碼  

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

c.保證JSP的頁面編碼與上面兩個的charset相同,這點我有在文章的第一點說過。

上面的字符集可以根據需要自己靈活選擇,不一定非要utf-8。不過因為utf-8對各國語言,特別是中文支持較好,所以推薦使用。我就曾經遇到過滘在GB2312編碼的頁面無法正常顯示的問題。

5.Post和Get傳遞中文,后臺獲取亂碼。

前臺傳遞中文也分為Get和Post方法。

a.Get方法的情況:

Get方法的時候主要是URL傳遞中文。

如果是在js文件中,可以使用如下代碼進行中文轉碼。

Js代碼  

 
?
1
 
2
var url ="http://www.baidu.com/s?industry=編碼"
url = encodeURI(url);

如果是在jsp文件中,則可以使用如下語句進行轉碼。
頁面開始引入:

Java代碼  

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

      需要轉碼的地方使用URLEncoder進行編碼:

Js代碼  

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

無論使用哪種方法,在后臺獲取中文的時候都要使用如下代碼:

Java代碼  

 
?
1
 
2
3
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的字符集,如:

Js代碼  

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

其中param為要傳遞的參數。

后臺部分和get方法一樣,設置如下即可,注意傳輸和接受的字符集要統一。

 6.后臺向前臺傳遞中文亂碼。

在這里提供一個函數,通過這個函數來發送信息,就不會出現亂碼,核心思想也是設置response流的字符集。函數代碼如下:

Java代碼  

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * @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代碼  

 
?
1
 
2
3
4
5
6
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緩存的,清空請求前部的一些空白行。 

以上只是做了比較簡單的總結,具體亂碼有的時候可能是多個情況的組合,具體問題具體分析。如果錯誤歡迎指正。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩成人在线播放 | 精品一区二区av | 欧美激情精品久久久久久变态 | 亚洲精品一区二区三区在线 | 日韩资源| 国产精品久久久久久久久久久久久 | 激情网页 | 免费黄色网止 | 精品国产不卡一区二区三区 | 在线中文 | 国产免费看 | 成人亚洲天堂 | 亚洲成a人v欧美综合天堂麻豆 | 亚洲色图p | 欧美国产日韩一区 | 亚洲色图一区二区三区 | 国产精品毛片一区二区三区 | 日韩成人av在线 | 午夜伦理电影 | www.久久.com| 欧美精品成人 | 在线观看不卡 | 亚洲精品国产区欧美区在线 | 午夜av影院| 欧美性猛片 | 成人精品久久久 | 99精品国产高清在线观看 | 亚洲在看| 婷婷色综合 | 九九资源站 | 亚洲精品一区二区三区在线观看 | 成人免费一区二区三区视频网站 | 午夜精品久久久久久久久久久久久 | 欧美日韩激情 | 精品日韩在线观看 | 日韩综合网| 成人午夜精品一区二区三区 | 久艹在线 | 最新国产视频 | 91精品免费 | 成人h视频 |