JavaWeb开发编码与乱码总结

简介:

自我总结

1.getBytes()和new String()方法

 ▇  public byte[] getBytes(Charset charset)方法

    这个方法是将字符串按指定的字符集进行编码,转换成字节数组。如果不指定字符集,默认采用

 系统自带的字符集。

    采用不同的字符集,对于同一个带有中文的字符串,得到的字节数组的是各不相同的。因为一个

 中文字符使用不同的编码方式,得到的字节长度是不同的。(可以通过将一个中文字符不同的编码转

 换成字节数组,然后再打印数组的长度)

    byte[] b_gbk = "中".getBytes("GBK");     //2个字节   
     byte[] b_utf8 = "中".getBytes("UTF-8");    //3个字节
     byte[] b_iso88591 = "中".getBytes("ISO8859-1");  //1个字节

    byte[] b_iso88591 = "中".getBytes("UNICODE");  //4个字节       

  String(byte[] bytes, Charset charset)

    通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String如果不指定字符集,

 默认采用系统自带的字符集。

 

     String s_gbk = new String(b_gbk,"GBK");        // 输出“中”
      String s_utf8 = new String(b_utf8,"UTF-8");       //  输出“中”      

      String s_iso88591 = new String(b_iso88591,"ISO8859-1");  //   输出乱码

     通过输出s_gbk、s_utf8和s_iso88591,会发现s_gbk和s_utf8都是"中",而只有s_iso88591是一个不被识别的字

   符(可以理解为乱码),为什么使用ISO8859-1编码再组合之后,无法还原"中"字?原因很简单,因为ISO8859-1编码

   的编码表根本就不包含汉字字符,当然也就无法通过"中".getBytes("ISO8859-1");来得到正确的"中"字在

   ISO8859-1中的编码值了,所以,再通过new String()来还原就更是无从谈起。

    因此,通过String.getBytes(String decode)方法来得到byte[]时,一定要确定decode的编码表中确实存在

   String表示的码值,这样得到的byte[]数组才能正确被还原。

   有时候,为了让中文字符适应某些特殊要求(如http header要求其内容必须为iso8859-1编码),可能会

  通过将中文字符按照字节方式来编码的情况,如:

  String s_iso88591 = new String("中".getBytes("UTF-8"),"ISO8859-1"),这样得到的s_iso8859-1

  字符串实际是三个在ISO8859-1中的字符,在将这些字符传递到目的地后,目的地程序再通过相反的方式

  String s_utf8 = new String(s_iso88591.getBytes("ISO8859-1"),"UTF-8")来得到正确的中文汉

  字"中",这样就既保证了遵守协议规定、也支持中文。  

   上面这个过程的专业术语叫做逆向编解码,注意顺向编码的时候getBytes()采用utf-8,这个编码必需

  要支持中文。否则还是会出现乱码。 

2.常见字符集  

    ASCII( American Standard Code for Information Interchange ):美国标准信息交换码

      基本的 ASCII 字符集共有 128 个字符,其中有 96 个可打印字符,包括常用的字母、数字、标点符号等,

             另外还有 32 个控制字符(如回车、空格、换行等)。ASCII码使用7位2进制数表示一个字符,7位2进制数可以

             表示出2的7次方个字符,共128个字符。

      字母和数字的 ASCII 码的记忆是非常简单的。我们只要记住了一个字母或数字的 ASCII 码(例如记住 A 为

             65 , 0 的 ASCII 码为 48 ),知道相应的大小写字母之间差 32 ,就可以推算出其余字母、数字的 ASCII 

             码。

     0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符),如控制符:LF(换行)、CR(回

    车)、FF(换页)、DEL(删除)、BS(退格)、BEL(振铃)等;通信专用字符:SOH(文头)、EOT(文

    尾)、ACK(确认)等;ASCII值为8、9、10和13分别转换为退格、制表、换行和回车字符。它们并没有特定的

    图形显示,但会依不同的应用程序而对文本显示有不同的影响。

      32~126(共95个)是字符(32sp是空格),其中48~57为0到9十个阿拉伯数字,65~90为26个大写英文字

    母,97~122为26个小写字母,其余为一些标点符号、运算符号等。

      ANSI(MBCS)     

                    为了扩充ASCII编码,以用于显示本国的语言,不同的国家和地区制定了不同的标准,由此产生了

              GB2312, BIG5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 

             ANSI 编码,又称为"MBCS(Muilti-Bytes Charecter Set,多字节字符集)"。在简体中文系统下,ANSI 编码代

            表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码,所以在中文 windows下要转码成gb2312,gbk

            只需要把文本保存为ANSI 编码即可。 不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种

            语言的文字,存储在同一段 ANSI 编码的文本中。一个很大的缺点是,同一个编码值,在不同的编码体系里代表

            着不同的字。这样就容易造成混乱。导致了unicode码的诞生。其中每个语言下的ANSI编码,都有一套一对一的

            编码转换器,Unicode变成所有编码转换的中间介质。所有的编码都有一个转换器可以转换到Unicode,而

            Unicode也可以转换到其他所有的编码。

             ▇     GB2312

    GB 2312是一个简体中文字符集(详情请百度)

                     GB2312采用了二维矩阵编码法对所有字符进行编码

                     GB2312字符在计算机中存储是以其区位码为基础的,其中汉字的区码和位码分别占一个存储单元,每个

              汉字占两个存储单元。由于区码和位码的取值范围都是在1-94之间,这样的范围同西文的存储表示冲突。

             ▇   GBK

      GB 2312的出现,基本满足了汉字的计算机处理需要,但对于人名、古汉语等方面出现的罕用字,GB 

              2312不能处理,这导致了后来GBK及GB 18030汉字字符集的出现。   

                     GBK编码标准兼容GB2312,简、繁体字融于一库。

                     GBK采用双字节表示,字符有一字节和双字节编码,00–7F范围内是一位,和ASCII保持一致。

             ▇    Big5

                      大五码是一种繁体中文汉字字符集(由来请百度)

    Unicode

                     如果有一种编码,将世界上所有的符号都纳入其中,无论是英文、日文、还是中文等,大家都使用这个

             码表,就不会出现编码不匹配现象。每个符号对应一个唯一的编码,乱码问题就不存在了。这就是Unicode编

             码。   

                    Unicode固然统一了编码方式,但是它的效率不高,比如UCS-4(Unicode的标准之一)规定用4个字节存储

             个符号,那么每个英文字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。(怪不得编程的时候不

             采用这种编码方式)

    ▇ UTF-8

      为了提高Unicode的编码效率,于是就出现了UTF-8编码。UTF-8可以根据不同的符号自动选择编码的长

             短。比如英文字母可以只用1个字节就够了。    

    ▇ ISO-8859-1

      ISO-8859-1编码是字节编码,向下兼容ASCII,它不支持中文,只支持几乎欧洲所有国家的语言。但它

             的使用十分的广泛,因为大多编程软件都是由外国人制作的。   

    ▇ Base64    

    一端发送GB2312编码->根据Base64规则->转换成ASCII码,接收端收到ASCII码->根据Base64规则-

             >还原到GB2312编码。   

3.Web打印中文数据和提交中文数据乱码问题(服务用的是tomcat)

   不管是从服务器向客户端打印数据,还是从客户端向服务器提交数据。数据的交互传输都是以流的方式进行的

             1)提交中文数据

                   在服务器端,可以通过request.getParameter()方法得到某一个表单数据,实际客户端传输的是按浏览器默

             认字符集编码之后的字节数据(表单数据.getBytes(浏览器默认字符编码)),数据到达了tomcat服务器,

             tomcat默认使用iso8859-1字符集来解码表单提交过来的字节数据,即执行new String(客户端提交的byte[]数

             组,tomcat默认解码字符集)。

      >>对于post提交,数据会先放到request缓冲区中,由于request缓冲区的默认字符集(iso8859-1)是可以进

            行修改的,通过request.setCharacterEncoding(decode)方法,那么tomcat在解码的时候就会按照指定字符集来

            解码。

                    例子:一般浏览器的默认编码字符集是utf-8,用post提交中文数据,会向服务器发送字节数组,“中

                              文”.getBytes("utf-8");在服务器端设置request.setCharacterEncoding("utf-8")。那么服务器通过

                              request.getParameter()得到的字符串就是new String("中文“.getBytes("utf-8"),"utf-8"),编解码方式

                              一致,自然不会出现中文乱码的情况了。

                     >>对于get提交数据不会放到request缓冲区中,所以无法修改tomcat解码的默认字符集iso8859-1,那

            么通过request.getParameter()方法得到字符串就是乱码了。            

                    例子:一般浏览器的默认编码字符集是utf-8,用post提交中文数据,会向服务器发送字节数组,“中

                              文”.getBytes("utf-8");那么服务器通过request.getParameter()得到的字符串就是new String("中

                              文“.getBytes("utf-8"),"iso8859-1"),编解码方式不一致,肯定就乱码了。

                    那么,应该如何解决get提交中文乱码的问题呢?

                    方式一:修改tomcat的server.xml文件,将URLEncoding改为utf-8(浏览器提交数据时采用的字符集)。

                             这种直接修改服务器配置的方式,类似于硬编码机制,一般不用这种方法。

                            wKioL1Wvq-bzR7z4AABR_1L4Jb4749.jpg

                    方式二:逆向编解码

                            data = URLEncoder.encode(data,"iso8859-1");

                            data = URLDecoder.decode(data,"utf-8");

                    方式三:逆向编解码的简写方式

                            data = new String(data.getBytes("iso8859-1"),"utf-8");

                    当然get提交这3种解决中文乱码的方法也同样适用于post提交。




         



















转载

1.那些年JavaWeb的各种中文乱码终极解决方法

   http://www.2cto.com/kf/201209/157773.html


2.java web 开发中的乱码解决方案自我总结

    http://blog.csdn.net/baoyinwang/article/details/7457087

3.字符集和字符编码(Charset & Encoding)

    http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html

4.深入分析 Java 中的中文编码问题

    http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/



      本文转自屠夫章哥  51CTO博客,原文链接:http://blog.51cto.com/4259297/1671871,如需转载请自行联系原作者





相关文章
|
14天前
|
监控 JavaScript 前端开发
《理解 WebSocket:Java Web 开发的实时通信技术》
【4月更文挑战第4天】WebSocket是Java Web实时通信的关键技术,提供双向持久连接,实现低延迟、高效率的实时交互。适用于聊天应用、在线游戏、数据监控和即时通知。开发涉及服务器端实现、客户端连接及数据协议定义,注意安全、错误处理、性能和兼容性。随着实时应用需求增加,WebSocket在Java Web开发中的地位将更加重要。
|
28天前
|
Web App开发 SQL Java
javaweb实现分页(二)
javaweb实现分页(二)
18 1
|
28天前
|
SQL 关系型数据库 MySQL
javaweb实现分页查询(一)
javaweb实现分页查询(一)
17 0
|
28天前
|
SQL 关系型数据库 MySQL
javaweb中实现分页,持续更新……
javaweb中实现分页,持续更新……
15 1
|
3天前
|
Web App开发 Java 应用服务中间件
【Java Web】在 IDEA 中部署 Tomcat
【Java Web】在 IDEA 中部署 Tomcat
11 0
|
6天前
|
Java API
编码的奇迹:Java 21引入有序集合,数据结构再进化
编码的奇迹:Java 21引入有序集合,数据结构再进化
13 0
|
6天前
|
Java Shell
Java 21颠覆传统:未命名类与实例Main方法的编码变革
Java 21颠覆传统:未命名类与实例Main方法的编码变革
10 0
|
7天前
|
运维 NoSQL 算法
Java开发-深入理解Redis Cluster的工作原理
综上所述,Redis Cluster通过数据分片、节点发现、主从复制、数据迁移、故障检测和客户端路由等机制,实现了一个分布式的、高可用的Redis解决方案。它允许数据分布在多个节点上,提供了自动故障转移和读写分离的功能,适用于需要大规模、高性能、高可用性的应用场景。
15 0
|
9天前
|
人工智能 小程序 Java
JAVA开发智慧学校系统源码+人脸电子班牌布局
智慧校园是通过利用物联网,大数据技术来改变师生和校园资源相互交互的方式,以便提高交互的明确性、灵活性和响应速度,从而实现智慧化服务和管理的校园模式。
|
15天前
|
XML JSON JavaScript
使用JSON和XML:数据交换格式在Java Web开发中的应用
【4月更文挑战第3天】本文比较了JSON和XML在Java Web开发中的应用。JSON是一种轻量级、易读的数据交换格式,适合快速解析和节省空间,常用于API和Web服务。XML则提供更强的灵活性和数据描述能力,适合复杂数据结构。Java有Jackson和Gson等库处理JSON,JAXB和DOM/SAX处理XML。选择格式需根据应用场景和需求。