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,如需转载请自行联系原作者





相关文章
|
11天前
|
JavaScript 安全 Java
智慧产科一体化管理平台源码,基于Java,Vue,ElementUI技术开发,二开快捷
智慧产科一体化管理平台覆盖从备孕到产后42天的全流程管理,构建科室协同、医患沟通及智能设备互联平台。通过移动端扫码建卡、自助报道、智能采集数据等手段优化就诊流程,提升孕妇就诊体验,并实现高危孕产妇五色管理和孕妇学校三位一体化管理,全面提升妇幼健康宣教质量。
42 12
|
1月前
|
自然语言处理 Java
Java中的字符集编码入门-增补字符(转载)
本文探讨Java对Unicode的支持及其发展历程。文章详细解析了Unicode字符集的结构,包括基本多语言面(BMP)和增补字符的表示方法,以及UTF-16编码中surrogate pair的使用。同时介绍了代码点和代码单元的概念,并解释了UTF-8的编码规则及其兼容性。
112 60
|
15天前
|
网络协议 Java Shell
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
49 7
|
1月前
|
前端开发 Java 程序员
菜鸟之路day02-04拼图小游戏开发一一JAVA基础综合项目
本项目基于黑马程序员教程,涵盖面向对象进阶、继承、多态等知识,历时约24小时完成。项目去除了登录和注册模块,专注于单机游戏体验。使用Git进行版本管理,代码托管于Gitee。项目包含窗体搭建、事件监听、图片加载与打乱、交互逻辑实现、菜单功能及美化界面等内容。通过此项目,巩固了Java基础并提升了实际开发能力。 仓库地址:[https://gitee.com/zhang-tenglan/puzzlegame.git](https://gitee.com/zhang-tenglan/puzzlegame.git)
45 6
|
1月前
|
Java 应用服务中间件 API
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
45 5
|
1月前
|
SQL Java API
|
1月前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
38 4
|
1月前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
64 2
|
1月前
|
Kubernetes Java 持续交付
小团队 CI/CD 实践:无需运维,Java Web应用的自动化部署
本文介绍如何使用GitHub Actions和阿里云Kubernetes(ACK)实现Java Web应用的自动化部署。通过CI/CD流程,开发人员无需手动处理复杂的运维任务,从而提高效率并减少错误。文中详细讲解了Docker与Kubernetes的概念,并演示了从创建Kubernetes集群、配置容器镜像服务到设置GitHub仓库Secrets及编写GitHub Actions工作流的具体步骤。最终实现了代码提交后自动构建、推送镜像并部署到Kubernetes集群的功能。整个过程不仅简化了部署流程,还确保了应用在不同环境中的稳定运行。
82 9
|
2月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
1768 2
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)

热门文章

最新文章