java编码,乱码问题详解
一、常见的编码格式
1.ASCII
基础编码,英文和西欧字符。
用一个字节的低7位表示,一共128个。
0~13是控制字符如换行、回车、删除等,32~126是打印字符,键盘输入。
2.IOS-8859-1
ASCII的扩展。
用一个字节表示,一共256个。
3.GB2312
中文编码字符集。
用两个字节表示,A1~A9是符号区,一共682个;B0~F7是汉字区,一共6763个。
编码需要查询对应码表,效率略低。
4.GBK
GB2312的扩展,能够兼容GB2312。
用两个字节表示,一共23940个码位,表示21003个汉字。
编码需要查询对应码表,效率略低。
5.UTF-16
UTF-16具体定义了Unicode字符在计算机的存取方法。
用两个字节表示Unicode的转化格式。
定长的展示方法,每两个字节表示一个字符,转化效率高,内存和硬盘多用此编码(JAVA内存存储格式UTF-16)。
采用顺序编码,不能对单个字符的编码进行校验,如果损坏,后面的码值都会受影响。
6.UTF-8
UTF-8具体定义了Unicode字符在计算机的存取方法。
用1-6个字节组成一个字符,汉字采用三个字节表示。
变长的展示方法,每个编码区域有不同的字码长度。
网络传输中很大一部分字符用一个字节就可以展示,UTF-16规范化的全部转为了两个字节,对于这些字符UTF-8只需要一个字节。
UTF-8如果中间一个码值损坏,后面的码值并不受影响。
相对于UTF-16,UTF-8有传输中资源占用小,数据更安全的优势,更适合网络传输,但UTF-16的编码规则相对简单,编码效率更高,适合本地内存和磁盘。
二、常见JAVA编码API
1.I/O
InputStreamReader isr = new InputStreamReader(inputStream,"utf-8"); Charset StreamDecoder OutputStreamWriter osw = new OutputStreamWriter(outputStream,"utf-8"); Charset StreamEncoder
2.内存操作
字符与字节的转换:
//String
String s = "中文字符";
byte[] b = s.getBytes("UTF-8");
String s1 = new String(b,"UTF-8"); //Charset
Charset charset = Charset.forName("UTF-8");
ByteBuffer byteBuffer = charset.encode(string);
CharBuffer charBuffer = charset.decode(byteBuffer); //char和byte的软转换,将一个16bit的char拆分成两个8bit的byte来显示,实际值并没有被转换。
ByteBuffer heapByteBuffer = ByteBuffer.allocate(1024);
ByteBuffer byteBuffer = heapByteBuffer.putChar(c);
三、Java Web中涉及的编解码
1.URL编解码
PathInfo中文问题:
配置tomcat的server.xml:
<Connector URIEncoding="UTF-8"/>
QueryString中文问题:
QueryString是通过HTTP中的Header传到后台的,他的解码字符集默认是ISO-8859-1,
也可以通过Header的ContentType中的Charset来定义。
如何确定后端调取了ContentType中的字符集,需要在server.xml中配置(这个配置只针对QueryString有效):
<Connector useBodyEncodingForURI="true"/>
2.HTTP Header的编解码
针对Header中的其他参数,比如Cookie,redirectPath等。
尽量不要传递非ASCII字符,如果必须,在传递之前用下面的API进行编码再传递:
org.apache.catalina.util.URLEncoder
3.POST表单的编解码
客户端获取参数为乱码后的解决思路:
1.将POST改为get,查看浏览器端是否有问题。
2.后端request.geCharacterEncdoing返回结果是否是预期编码。
//在第一次使用request.getParameter之前使用
request.setCharacterEncoding(charset);
4.HTTP BODY的编解码
主要阐述从后台到前台的编解码:
//对返回前台的数据进行编码,前台会首先根据这个值进行解码
response.setCharacterEncoding(charset);
<!-- 如果后台没有设置,会根据页面中的charset来解码,如果页面也有设置则用默认编码来解码 -->
<meta HTTP-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<!-- JDBC读写数据时要和数据的内置编码保持一致 -->
url="jdbc:mysql://localhost:3306/DB?useUnicode=true&characterEncoding=UTF-8"
四、JS的编码问题
1.外部引入js文件
<!-- 浏览器会按照charset的设置来解析这个js文件,如果没有设置则默认按照当前页面的的编码设置来解析js文件 -->
<script src="de/mo/demo.js" charset="gbk"></script>
2.js的URL编码
//对url根据UTF-8进行编码和解码,除了一些特殊字符"!""#""$""&""'""("")""*""+"",""-"".""/"":"";""=""?""@""_""~""0-9""a-z""A-Z" //编码结果在每个码值前加一个"%"
encodeURI("http://localhost:8080/examples/servlets/servlet/来吧昆特牌吧孙子?inviter=杰洛特");
decodeURI("**编码内容**");
//对url根据UTF-8进行编码和解码,相对于encodeURI,它更加的彻底。排除的特殊字符为"!""'""("")""*""-"".""_""~""0-9""a-z""A-Z"
//编码结果在每个码值前加一个"%"
//它排除的字符比encodeURI更少,通常用于将URL作为参数的URL的编码,如示例如果不将参数URL中的&进行编码会影响到整个URL的完整性
"http://localhost/servlet?ref=" + encodeURIComponent("http://localhost:8080/examples/servlets/servlet/来吧昆特牌吧孙子?inviter=杰洛特&inviter=叶奈法");
decodeURIComponent("**编码内容**");
3.后端接收时解码
后端处理URL编解码靠的是 java.net.URLEncoder和java.net.URLDecoder这两个类。
后端对的对URL的编码同样也有排除的特殊字符,与前端的encodeURIComponent相对应。
//后端直接获取传过来的URL参数会自动解码
//如果没有提前设置request.setCharacterEncoding()很容易出现编码不同而导致的乱码
request.getParameter();
//另一种方式是通过前台js对URL进行两次编码,后台不管通过什么进行第一次解码,都能得到正确的UTF-8编码,前台代码如下
encodeURIComponent(encodeURIComponent(url));
//第一次编码的结果(例如:%E2%A7)的百分号,会在第二次编码后将%变成%25(例如:%25E2%25A7)
//后台在执行request.getParameter()的时候会自动解码,不管当前容器的编码是什么得到的是正确的UTF-8编码(例如:%E2%A7)
五、其他需要编码的地方
1.xml
<?xml version="1.0" encoding="UTF-8"?>
2.Velocity
services.VelocityService.input.encoding=UTF-8
3.JSP
<%@page contentType="text/html;charset=UTF-8"%>
注:本文是对“《深入分析Java Web技术内幕》许令波 著” 一书的相关内容的总结
java编码,乱码问题详解的更多相关文章
- Java版人脸检测详解下篇:编码
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- java web.xml配置详解(转)
源出处:java web.xml配置详解 1.常规配置:每一个站的WEB-INF下都有一个web.xml的设定文件,它提供了我们站台的配置设定. web.xml定义: .站台的名称和说明 .针对环境参 ...
- java web之Filter详解
java web之Filter详解 2012-10-20 0 个评论 作者:chenshufei2 收藏 我要投稿 .概念: Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,W ...
- 国际化,java.util.ResourceBundle使用详解
java.util.ResourceBundle使用详解 一.认识国际化资源文件 这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以: 轻松地本地化或翻译成不同的 ...
- java.util.ResourceBundle使用详解
java.util.ResourceBundle使用详解 一.认识国际化资源文件 这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以: 轻松地本地化或翻译成不同的 ...
- java.util.ResourceBundle使用详解(转)
java.util.ResourceBundle使用详解 一.认识国际化资源文件 这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以: 轻松地本地化或翻译成不同的 ...
- 【转】Eclipse Java注释模板设置详解
Eclipse Java注释模板设置详解 设置注释模板的入口: Window->Preference->Java->Code Style->Code Template 然后 ...
- Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送
Android高效率编码-第三方SDK详解系列(三)--JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送 很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送, ...
- Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!
Android高效率编码-第三方SDK详解系列(一)--百度地图,绘制,覆盖物,导航,定位,细腻分解! 这是一个系列,但是我也不确定具体会更新多少期,最近很忙,主要还是效率的问题,所以一些有效的东西还 ...
随机推荐
- 【linux】CPU,内存对网站的影响
如果读写非常多,建议内存大点 如果涉及到的计算非常多,那就升级CPU
- web前端的环境配置
1.1.WEB开发的相关知识 WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. Internet上供外界访问的Web资源分为: 静态web资源(如html 页 ...
- windows下软件安装目录
说明:该软件目录为自身在实际学习开发中系统下安装的目录,方便自己的查看以及和他人交流,如有软件需要,请留言,谢谢! 1) PADSVX.1.2 中级PCB绘图软件! 2) Caendece 17.2 ...
- 单片机入门学习笔记5:STC下载器
STC下载器主要集成了, 1.芯片识别,下载/编程 2.端口识别 3.串口助手 4.KEIL仿真设置 5.芯片选型 6.范例程序 (集成了定时器,串口等例程) 7.波特率计算器 8.定时器计算器 9. ...
- A1075 PAT Judge (25)(25 分)
A1075 PAT Judge (25)(25 分) The ranklist of PAT is generated from the status list, which shows the sc ...
- 动态规划:HDU1789-Doing Homework again
Doing Homework again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- 动态规划:HDU1248-钱币兑换问题
解题心得: (青蛙跳台阶:有n阶台阶,青蛙可以一次跳一阶也可以一次跳两阶,问总共有多好中跳法) 1.之前把这个问题的思路弄错了,以为是递推,就像青蛙跳台阶,用斐波那契求解.但是用斐波那契肯定会超范围. ...
- LeetCode刷题感想
断断续续用了半年的时间把LeetCode刷完了,之前复习了数据结构与算法.将刷题与复习数据结构结合起来会更有效果.总之不是为了刷题而刷题,而是为了巩固和补充一部分知识. LeetCode真的是一个很好 ...
- 海量数据处理算法—BitMap
1. Bit Map算法简介 来自于<编程珠玑>.所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了Bit为单位来存储数据,因此在存储空 ...
- Android四大组件之服务
创建一个服务,并与活动绑定 作为安卓四大组件之一的服务,毫无例外也要在manifast中进行注册 新建服务类继承于Service,并覆盖onBind( )方法,用于与活动绑定 public class ...