第三章 深入分析Java Web中的中文编码问题
3.1 几种常见的编码格式
3.1.1 为什么要编码
一个字节 byte只能表示0~255个符号,要表示更多的字符,需要编码。
3.1.2 如何翻译
ASCII码:有128个,用一个字节的低7位表示。
ISO-8859-1,能表示256个,是单字节编码。
GB2312: 双字节编码,
GBK:是对GB2312的扩展,加入更多汉字,和GB2312兼容,BG2312编码的汉字可以用GBK来解码,不会乱码。
GB18030:
UTF-16:Unicode(统一码),ISO创建的全新的超语言字典。Unicode是JAVA和XML基础。 注意: Unicode是编码,也就是码和汉字(或其他国家语言)的对应关系。但是具体如何把这些编码存储,则要采取不同的编码方式,比如UTF-16和UTF-8。UTF-16就用固定两个字节表示一个UNicode编码。因为是固定两个字节的长度,所以操作起来很简单,这也是JAVA以UTF-16作为字符的内存存储格式的原因。
UTF-8: UTF的缺点是浪费,因为很多字符用一个字节就够了,用不上两个字节。
UTF-8的编码规则: 如果一个字节最高位为0,XXX
如果一个字节以11开头,XXX
如果一个字节以10开头,XXX
3.2 在JAVA中需要编码的场景
什么场合需要编码
3.2.1 在I/O操作中存在的编码
在字符到字节或从字节到字符的转换,而这种转换的场景主要是I/O. I/O包括磁盘和网络两种I/O.
Reader类是在JAVA IO读字符的父类,而inputstream类是读字节的父类,InputStreamReader类就是关联字节到字符的桥梁,字节到字符的转换,而对具体字节到字符的编码实现,它又委托StreamDecoder去做,解码过程中必须制定Charset,如果没有制定,则将使用本地环境中的默认字符集,如在中文环境中使用GBK。
package ioTest; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException; public class decodeTest { public static void main(String[] args) {
String file = "XXX.txt";
String charset = "UTF-8";
try {
FileOutputStream outputStream = new FileOutputStream(file);
try {
OutputStreamWriter writer = new OutputStreamWriter(outputStream, charset);
try {
writer.write("要保存的中文字符");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
writer.close();
}
}
}
3.2.2 在内存操作中编码
字节和字符转换:
String s = "lfdasjlfjasljfasfa";
byte[] b = s.getBytes("UTF-8");
String n = new String(b, "UTF-8");
byte[] 和 char[]之间编码和解码:
String string = "fsdfsd";
Charset chars = Charset.forName("UTF-9");
ByteBuffer byteBuffer = chars.encode(string);
CharBuffer charBuffer = chars.decode(byteBuffer);
3.3 在JAVA中如何编码
3.3.1 按照ISO-8859-1编码
3.3.2 按照GB2312编码
3.3.3 按照GBK编码
3.3.4 按照UTF-16编码
3.3.5 按照UTF-8编码
3.3.6 编码UTF-8编码代码片段
3.3.7 几种编码格式的比较
GBK是对GB2312扩展,可以表示所有的汉字。
UTF-8比UTF-16更适合网络传输
3.4 在JAVA web中编解码
http请求过程中,存在编码的地方是:
前段发过啦来的URL, cookie, Parameters。
服务器接收到HTTP请求后,要解析HTTP,其中URL,cookie和POST表单参数需要解码。
服务器可能读网络和本地的文件和DB,可能存在编码问题。
当servlet处理完所有请求后,需要将这些数据再编码,发送给浏览器。
3.4.1 URL的编解码
URL可能存在中文,所以需要编码。
浏览器编码URL是将非ASCII字符按照某种编码格式编码成16进制数字后将每个16进制表示的字符前加上%。
浏览器可以设置编码格式。
Tomcat是如何解码的?
’URL的URI部分进行解码的字符集是在<Connector URIEncodeing="UTF-8">里设置的。
QueryString的解析过程:GET方式HTTP请求的querystring和POST方式HTTP请求的表单参数都是作为parameters保存的,都通过request.getParameter();
queryString的解码字符集是在哪定义的呢? 是在HTTP的header的contentType或者是默认的ISO-8859-1,如果要用HTTP的header中
中定义的编码需要设置<Connector URIEncoding="UTF-8" useBodyEncodingForURI='true'>
3.4.2 HTTP Header的编解码
除了上面的URL外,还可能在header中传递其他参数,如cookie,redirectPath等。这些用户设置的值也可能存在编码问题。
对Header的解码是在调用request.getHeader()时进行的。默认是按照ISO-8859-1,如果header中有非ASCII,会乱码。
如果要用header传递中文,可以传之前编码,然后解码:
1、客户端
method.addRequestHeader("hello",URLEncoder.encode("中文","UTF-8"));
2、服务器
value=URLDecoder.decode(value);
3.4.3 POST表单的编解码
POST表单提交的参数的解码是在第一次调用request.getParameter时发生的,与queryString不同,是通过HTTP的body传递的,当提交表单的时候,根据ContentType的charset编码格式对表单中填入的参数编码,然后提交到服务器,在服务器端也用contentType来解码。这个编码、解码的字符集使我们自己设置的。
注意一定要在第一次调request.getParameter方法之前就设置request.setCharacterEncoding(charset), 否则会乱码。
3.4.4 HTTP BODY的编解码
response.setCharacterEcoding可以设置编码方式,覆盖request.getCharacterEncoding的值,并且通过contentType返回给客户端。浏览器根据content-Type解码;如果么有这个值,按照HTML中的charset来解码。
和JDBC的编码方式要一致。
3.5 在JS中的编码问题
3.5.1 外部引入JS文件
如何js文件本身的编码和JS中使用的字符编码不一致,可能就有乱码。比如*.js文件是UTF-8,而页面是GBK,就会有乱码问题。
3.5.2 JS的URL编码
Ajax的http_request('get', url, ture)调用,URL在IE下用OS的默认编码,在Firefox下是UTF-8编码。
JS有三个函数是和编码解码相关的。
JAVA是如何来解码的?JAVA端处理URL编码、解码有连个类: 分别是Java.net.URLEncoder和java.net.URLDecoder
3.5.3 其他需要编码的地方
3.6 常见问题分析
3.6.1 中文变成了看不懂的字符
解码和编码用的字符集不一样,就会出现乱码。
3.6.2 一个汉字变成一个问号
ISO-8859-1遇到不认识的用3F表示,是问号。
3.6.3 一个汉字变成两个问号
3.6.4 一种不正常的正确编码
3.7 一种繁简转换的实现方式
3.8 总结
第三章 深入分析Java Web中的中文编码问题的更多相关文章
- 【中文乱码】深入分析 Java Web 中的中文编码问题
深入分析 Java Web 中的中文编码问题 1.几种常见的编码格式 1.1 为什么要编码 在计算机中存储信息的最小单元是 1 个字节,即 8 个 bit, 所以能表示的字符范围是 0 ~ 255 个 ...
- 第三章 深入分析Java Web的中文乱码问题(待续)
几种常见的编码格式 在Java中需要编码的场景 在Java中如何编解码 在Java Web中涉及的编解码 在JS中的编码问题 常见问题分析 一种繁简转换的实现方式
- 深入分析Java Web中的中文编码问题
要对Java Web项目进行编码原因: 1.在计算机中存储信息的最小单位是1个字节,即8个bit,所以能表示的字符范围是0~255个. 2.电脑需要表示的符号太多.无法用1个字节完全表示. 要解决这个 ...
- 深入分析Java Web中的编码问题
编码问题一直困扰着我,每次遇到乱码或者编码问题,网上一查,问题解决了,但是实际的原理并没有搞懂,每次遇到,都是什么头疼. 决定彻彻底底的一次性解决编码问题. 1.为什么要编码 计算机的基本单元是字节, ...
- Java Web中的中文编码
Java Web开发中经常会遇到中文编码问题,那么为什么需要编码呢?因为人类需要表示的符号太多,无法用1个字节来表示,而计算机中存储信息最小单元为1个字节.所以必须指定char与byte之间的编码规则 ...
- 《深入分析Java Web技术内幕》读书笔记 - 第1章 深入Web请求过程
第1章 深入Web请求过程 1 1.1 B/S网络架构概述 2 基于统一的应用层协议HTTP来交互数据. 1.2 如何发起一个请求 4 HTTP连接本质是建立Socket连接.请求实现方式:工具包如H ...
- 深入分析Java Web技术内幕(修订版)
阿里巴巴集团技术丛书 深入分析Java Web技术内幕(修订版)(阿里巴巴集团技术丛书.技术大牛范禹.玉伯.毕玄联合力荐!大型互联网公司开发应用实践!) 许令波 著 ISBN 978-7-121- ...
- JAVA Coder 的《深入分析Java Web 技术内幕》读书笔记
本文基于<深入分析Java Web 技术内幕> <深入分析Java Web 技术内幕>,作者是 许令波,电子工业出版社.本文只是记录书本当中的精彩部分,作个人回顾和技术分享,请 ...
- 深入分析Java Web技术内幕
深入web请求过程 发起一个http请求的过程就是建立一个socket通信的过程 HTTPClient是一个开源的实现了http请求的工具包 深入分析java I/O的工作机制 深入分析java We ...
随机推荐
- 监控和审计IBM InfoSphere BigInsights和Cloudera Hadoop的访问权限
http://www.ithov.com/server/124456.shtml 您也将学习一个仅适用于 IBM InfoSphere BigInsights 的快速启动监控实现. 大数据骚动主要集中 ...
- Ceph配置项动态变更机制浅析
转自:https://www.ustack.com/blog/ceph%e9%85%8d%e7%bd%ae%e9%a1%b9%e5%8a%a8%e6%80%81%e5%8f%98%e6%9b%b4%e ...
- IOS-RunTime应用
什么是Runtime 总结起来,iOS中的RunTime的作用有以下几点: 1.发送消息(obj_msgSend) 2.方法交换(method_exchangeImplementations) 3.消 ...
- Elasticsearch压缩索引——lucene倒排索引本质是列存储+使用嵌套文档可以大幅度提高压缩率
注意:由于是重复数据,词法不具有通用性!文章价值不大! 摘自:https://segmentfault.com/a/1190000002695169 Doc Values 会压缩存储重复的内容. 给定 ...
- 【lightoj-1025】The Specials Menu(区间DP)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1025 [题目大意] 求一个字符串删去任意字符可以构成多少个不同的回文串 [分析 ...
- 背景色与WM_ERASEBKGND
1.背景模式 SetBkMode(TRANSPARENT/OPACITY) 用来反应文字,图形与窗口背景交互混合模式.透明则表示文字背景与窗口背景之间透明,互不干扰. 2.背景颜色 SetBkColo ...
- ng 实现插入和删除
结果: 代码: <!DOCTYPE html> <html ng-app="myApp"> <head lang="en"> ...
- PHP内核研究
深入理解PHP内核:Think In PHP Internals(TIPI)是一个开源项目 ,分享PHP内部实现的细节,如内核,扩展等.官网见:http://www.php-internals.com ...
- POJ 2029 Palindromes _easy version
#include<cstdio> #include<cstring> using namespace std; int main() { int n; ]; scanf(&qu ...
- RecyclerView 初体验
网上看了很多 RecyclerView 的教程,也结合学长的代码,终于实现了一个不错看的过去的List 可以通过左滑删除Item 长按Item或者点击按钮,可以对Item进行拖拽 更具体的内容会写在代 ...