前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >中文编码问题详解

中文编码问题详解

作者头像
洋仔聊编程
发布2019-01-15 17:31:48
3K0
发布2019-01-15 17:31:48
举报

一.常见的编码

ASCII,ISO-8859-1,GB2312,GNBK,UTF-8,UTF-16等

编码格式

表示个数

所需字节数

说明

ASCII

128

单字节的低七位表示

0~31为控制字符如回车换行等;32~126为打印字符,可键盘输入能够显示出来

ISO-8859-1

表示256个字符

单字节

扩展ASCII码,ISO8859-1到ISO8859-15,ISO8859-涵盖大多数西欧语言字符,应用最广泛。

GB2312

7445

双字节

A1~A9是符号区,682个;B0~F7是汉字区,共6763个汉字。

GBK

23940

双字节

扩展自GB2312,支持更多汉字,范围从8140~FEFE(去掉XX7F),能表示21003汉字,兼容GB2312。

GBK18030

兼容GB2312

应用不广泛

应用不广泛

UTF-16

处理Unicode编码

双字节

用2字节表示Unicode的转化格式,任何字符都通过2个字节表示,定长表示,效率快,java以UTF-16内存的字符存储格式。适合在本地磁盘和内存之间使用,可以达到字符和字节快速切换。

UTF-8

处理unicode编码

变长

每个编码区域不同字码长度,不同类型字符可以由1~6个字节组成,节省空间,效率不如utf-16,介于gbk和uft-16之间,适合网络传输,对ASCII码单字节存储,单字符损坏不影响后面字符。其通过首字节的前2位确定需要几个字节表示。

说明:unicode是统一码,ISO创建的全新的超语言字典,所有语言都可以通过这个字典相互翻译。

二.java中需要编码的场景

1.磁盘I/O操作中存在的编码

Reader类是java中读取字符的父类

InputStream是读取字节的父类

InputStreamReader类是关联字节到字符的桥梁,它负责在I/O中处理字节到字符的转换

具体字节到字符的解码实现它委托StreamDecoder类去做,在解码过程中必须由用户指定通过Charset指定编码格式,如果不指定会使用系统自带的编码格式.

Writer,OutputStream,OutputStreamWriter类的情况类似.

例如

代码语言:javascript
复制
String file = "D:/a.txt";
String charset = "UTF-8";
//写字符转化为字节流
FileOutputStream outputStream = new FileOutputStream(file);
//创建OutputStreamWriter对象
OutputStreamWriter writer = new OutputStreamWriter(outputStream,charset);
writer.write("这是内容");
writer.close();

//读取字节转化为字符
FileInputStream inputStream = new FileInputStream(file);
//创建InputStreamReader
InputStreamReader reader = new InputStreamReader(inputStream,charset);
//创建拼接字符串
StringBuffer stringBuffer = new StringBuffer();
char[] buf = new char[64];
int count = 0;
while ((count = reader.read(buf)) != -1){
stringBuffer.append(stringBuffer,0,count);
}
reader.close();

2.内存操作中编码

2.1 String提供了转换字节的方法

代码语言:javascript
复制
String s = "内容";
//字符串转换为字符数组
buye[] b = s.getBytes("UTF-8);
//字符数组转换为字符串
String n = new String(b,"UTF-8");

2.2 Charset类

代码语言:javascript
复制
//规定编码
Charset charset = Charset.forName("UTF-8");
//字符转换为字节
ByteBuffer buf = charset.encode("内容");
//字节转换为字符
CharBuffer buf2 = charset.decode(buf);

2.3 ByteBuffer类

ByteBuffer的用法:

代码语言:javascript
复制
//字符转换为字节
//创建一个容量为256字节的ByteBuffer
ByteBuffer buf = ByteBuffer.allocate(1024);
ByteBuffer buf1 = buf.putChar(c);

三.几种编码格式比较

1.GB2312与GBK

GBK是GB2312的升级版,GBK可以处理所有的汉字字符,而GB2312包含的中文字符不全,所以GB2312和GBK去比较,应该选择GBK

2.UTF-16和UTF-8

UTF-16编码效率最高,但不适合网络之间传输,占用空间也比较大,因为全部编码为双字节

UTF-8编码效率处在UTF-16和GBK之间,适合网络传输数据,是理想的中文编码方式

四.java web中需要编码的场景

1.网络I/O操作中存在的编码

1.1 数据经过网络传输都是以字节为单位的,则所有的数据都必须能够被序列化字节.

1.2 用户的一个HTTP请求,所需要编码的地方:URL,Cookie,Paramiter.

1.3 URL编解码:引用大佬的博客,写的非常详细

http://www.cnblogs.com/liuhongfeng/p/5006341.html

1.4 HTTP Header编码

在Header中传递的参数包含Cookie,redirectPath等.

如果在Header中传递非ASCII字符时,需要将这些字符用org.apache.catalina.util.URLEncoder编码才可.

1.5 POST表单的编解码

POST表单提交的参数的解码在第一次调用request.getParameter时发生,POST表单参数通过http的body传递到服务端。

整个流程是点提交时,浏览器根据contenttype的charset对表单参数编码,提交到服务端,服务端同样用contenttype中的字符集进行解码,所以post表单的参数一般不会乱码。

通过request.setCharacterEncoding(charset)可以设置。

注意:要在第一次调用request.getParameter方法之前设置request.setCharacterEncoding(charset),否则POST表单提交的数据可能出现乱码。

1.6 HTTP BODY编解码

服务端返回的结果经过编码返回浏览器,浏览器解码,然后显示。

编码可以通过response.setCharacterEncoding设置,会覆盖request.setCharacterEncoding的值,通过Header的content-type返回给客户端。

浏览器首先根据Content-type解码,无则根据HTML的来解码,无则使用浏览器默认编码解码。

2.JS中的编码问题

2.1 js文件编解码

<html>

<head>

<script src="xxx/a.js" charset="gbk"/>

引入的js文件若有中文,和本html页面的编码若不一致则会乱码,可以手动指定编码格式。

2.2 js的url编解码

js中发起ajax请求的url默认编码受浏览器不同影响,可使用encodeURI()、encodeURIComponent()几个函数。

encodeURL():可以将整个URL中的字符进行UTF-8编码,在背个码值之前添加"%"

注意:java中的URLEncoder、URLDecoder和js的encodeURIComponent对应。

2.3 xml文件的编解码

xml文件开始设定encoding

2.4 velocity模板设置编码

services.VelocityService.input.encoding=UTF-8

2.5 jsp设置编码

jsp页面<%@page >里面设置charset

五.编码的常见问题

1.中文变成了看不懂的字符

因为字符串解码时使用的字符集和编码字符集使用不一致所导致的.将字符集使用一致即可

2.中文变成了问号,一个中文变为一个问号

因为该字符串经过了不支持中文的ISO-8859-1编码后所出现的问题.换为GBK或者UTF-8即可

3.中文变成了问号,一个中文变为两个问号

这种情况比较复杂,中文经过了多次编码才会出现,需要检查中间的编码环节才可.

4.使用request.getParameter(name);出现乱码

因为配置文件中将useBodyEncodingForURL配置项没有设置为true,从而造成第一次解析用ISO-8859-1来解析.设置为true即可.

--本博文为博主在学习《深入分析java web 技术内幕》一书时所写。这本书不错,推荐给大家。

--本博文书写借鉴了博友的博客,在此表示感谢.

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年09月04日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.常见的编码
  • 二.java中需要编码的场景
  • 三.几种编码格式比较
  • 四.java web中需要编码的场景
  • 五.编码的常见问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com