0

0

Java中乱码问题的解决方法分享

黄舟

黄舟

发布时间:2017-07-20 14:13:16

|

1848人浏览过

|

来源于php中文网

原创

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编码才能相互转换

立即学习Java免费学习笔记(深入)”;

2.不同字符集的字符串转换时导致的乱码。

每一个String,底层实现都是用一个byte数组存储,使用不同的字符集,存储的数组长度当然就不同。如果不使用同一种字符集进行解码,就一定会出现乱码。

例如如下代码:

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了。

测试例子如下:

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,在生成一个String的时候就必须使用相应的编码,否则就会出现乱码。
简单来讲,只有满足如下公式的String转码,才不会乱码。

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没有出现乱码。代码如下:

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不会。 

Kuwebs企业网站管理系统3.1.5 UTF8
Kuwebs企业网站管理系统3.1.5 UTF8

酷纬企业网站管理系统Kuwebs是酷纬信息开发的为企业网站提供解决方案而开发的营销型网站系统。在线留言模块、常见问题模块、友情链接模块。前台采用DIV+CSS,遵循SEO标准。 1.支持中文、英文两种版本,后台可以在不同的环境下编辑中英文。 3.程序和界面分离,提供通用的PHP标准语法字段供前台调用,可以为不同的页面设置不同的风格。 5.支持google地图生成、自定义标题、自定义关键词、自定义描

下载

4.JSP中显示中文的乱码。

有的时候JSP页面在显示中文的时候会有乱码,大多数情况就是字符集配置和页面编码的问题。只要保证如下的几个配置没有问题,一般就不会有乱码出现。

a.JSP页面顶端添加如下语句:

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

b.在HTML的head标签中添加如下语句。

c.保证JSP的页面编码与上面两个的charset相同,这点我有在文章的第一点说过。

上面的字符集可以根据需要自己灵活选择,不一定非要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进行编码:

">

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

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速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
云朵浏览器入口合集
云朵浏览器入口合集

本专题整合了云朵浏览器入口合集,阅读专题下面的文章了解更多详细地址。

20

2026.01.20

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

28

2026.01.20

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

149

2026.01.19

java用途介绍
java用途介绍

本专题整合了java用途功能相关介绍,阅读专题下面的文章了解更多详细内容。

120

2026.01.19

java输出数组相关教程
java输出数组相关教程

本专题整合了java输出数组相关教程,阅读专题下面的文章了解更多详细内容。

41

2026.01.19

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

10

2026.01.19

xml格式相关教程
xml格式相关教程

本专题整合了xml格式相关教程汇总,阅读专题下面的文章了解更多详细内容。

14

2026.01.19

PHP WebSocket 实时通信开发
PHP WebSocket 实时通信开发

本专题系统讲解 PHP 在实时通信与长连接场景中的应用实践,涵盖 WebSocket 协议原理、服务端连接管理、消息推送机制、心跳检测、断线重连以及与前端的实时交互实现。通过聊天系统、实时通知等案例,帮助开发者掌握 使用 PHP 构建实时通信与推送服务的完整开发流程,适用于即时消息与高互动性应用场景。

23

2026.01.19

微信聊天记录删除恢复导出教程汇总
微信聊天记录删除恢复导出教程汇总

本专题整合了微信聊天记录相关教程大全,阅读专题下面的文章了解更多详细内容。

168

2026.01.18

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.7万人学习

C# 教程
C# 教程

共94课时 | 7.2万人学习

Java 教程
Java 教程

共578课时 | 48.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号