目录
乱码问题的由来
编码与解码
· 理论解释
字符编码(英语:Character encoding)也称字集码,
字集码是把字符集中的字符 编码 为指定集合中某一对象(例如:比特模式、自然数序列、8位组或者电脉冲)以便文本在计算机中存储和通过通信网络的传递。【1】码元是每个字符生成编码的比特位数。
即
形式上,是从 字符(集) ---- 到------> 特定二进制
载体上 人–> 机器
常见编码方式 | 中文字节数 | 英文字节数 | 对应字符 |
---|---|---|---|
ASCII | 1 | 拉丁字母 | |
ISO-8859-1 | 1 | 欧洲码 | |
GB2312 | 2 | 1 | 汉字+拉丁字母 |
GBK | 2 | 1 | 汉字扩展 |
UTF-8 | 3 | 1 | 所有语言 |
· 形象解释
有一个比较经典的例子。
比如你在某地看到这样一句话——“南京市长江大桥”。
在只有文字,没有语音,且没有过往经验的情况下,你可能把这句话理解为:
也可以理解为:
这就造成了,在没有事先约定规则的情况下,对同样的一段文字,不同的人可能有不同的理解方式(解码规则不同),使得文字产生歧义。
- java中的编解码
在java 的IO中,有两种流,一种是字符流,一种是字节流,二者在转换时,容易产生乱码问题。
通过如下代码查看默认编码:
System.out.println(Charset.defaultCharset());
按照 GB2312 得到字节(得到多字节字符串)
编码(字符集–>二进制)
String string = "中文123";
byte [] bytes = string.getBytes("GB2312");
按照 GB2312 从字节 得到字符串
解码(二进制—>字符集)
string = new String(bytes, "GB2312");
要将 String 按照某种编码写入文本文件,有两种方法:【2】
// 第一种办法:用 Stream 类写入已经按照指定编码转化好的字节串
OutputStream os = new FileOutputStream("1.txt");
os.write(bytes);
os.close();
// 第二种办法:构造指定编码的 Writer 来写入字符串
Writer ow = new OutputStreamWriter(new FileOutputStream("2.txt"), "GB2312");
ow.write(string);
ow.close();
注意:设置编码或者解码格式的操作,一定要在创建流之前或者创建流的构造函数之中,即编解码设定不能晚于流的创建。
乱码产生的原因
本质上,是编码过程和解码过程使用的 编码方式 不一致造成的乱码。
Java Web中乱码问题
在java web中,设计多处可能出现乱码的地方。下面按照不同位置,由内向外的顺序分别介绍。
统一将编码设置为UTF-8。
1 设定开发环境的编码
2 在数据库中
·(1)创建数据库
CREATE DATABASE `vhr` DEFAULT CHARACTER SET utf8;
·(2)创建数据表
DROP TABLE IF EXISTS `adjustsalary`;
CREATE TABLE `adjustsalary` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`eid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3 Java和数据库的连接过程中(JDBC)
url=jdbc:mysql://127.0.0.1:3306/UserModel?useUnicode=true&characterEncoding=UTF-8
4 在Servlet中
请求(浏览器–>服务器)乱码
- 浏览器请求方式为post
request.setCharacterEncoding("UTF-8");
- 浏览器请求方式为get
(1)手动设置字符串参数编码和解码方式
String name=request.getParameter("username");
String s1 = new String(name.getBytes("iso8859-1"), "UTF-8");
(2)修改文件 conf\server.xml
直接在 Tomcat 配置文件中解决,
修改 Tomcat 的 conf/server.xml 标签 中增加URIEncoding属性,值为UTF-8
不建议使用这种方式
原因是
- 1 部署的服务器不一定是tomcat
- 2 远程部署的时候,需要修改远程服务器的配置文件,可能修改权限不够
响应(服务器—>浏览器)乱码
- 字符流
//设置response的数据编码
response.setCharacterEncoding("UTF-8");
//浏览器打开时的编码方式
response.setContentType("text/html;charset=UTF-8");
//输出流
PrintWriter out=response.getWriter();
out.println("<script type='text/javascript' >alert('删除成功');</script>");
- 字节流
String data="中国 ";
//控制浏览器以什么码表打开
response.setHeader("Content-type", "text/html;charset=UTF-8");
OutputStream out=response.getOutputStream();
//设置写入response的数据编码
out.write(data.getBytes("UTF-8"));
在JSP页面中(服务器—>浏览器)
文件头设置
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
参考文献
【1】字符编码
【2】编码与解码本质
【3】JavaWeb 乱码问题终极解决方案!