Java开发中的编码问题总结

Wesley13
• 阅读 432

Java中的中文编解码问题一直以来令开发者比较头疼,这在Web开发中表现尤为突出。网上的解决方案琳琅满目,但一般是针对于一个特定问题的。我自己在开发过程中也是多次遇到过这种问题,经过冷静分析和查阅参考资料问题也都得以解决(或许解决方案不是最佳的)。但是每一次的解决并没有为下一次问题的出现提供特别好的联想效果。今天特地在这里将Java开发中的中文编解码问题做一下总结。

首先,先来说一下可能遇到中文编解码问题的场景。主要就是在 IO操作的环境中出现这种编解码问题(这么描述也不知道是不是合适)。比如说,从文件中读取数据来展示,从数据库中读取数据来展示,从第三方接口(WebService接口、JS接口、Http接口等)获取数据来展示…
Java处理字符的基本原理又是什么呢?我大体说一下,自己理解的也没有多么深入。各位Java开发者应该都清楚,Java使用Unicode编码来存储字符数据,具体使用的是UTF-16,UTF-16采用的是定长的双字节编码。Java在处理字符时采取三步走:
1、 按照某种编码从文件中读取字符数据
2、 将读取的数据以Unicode(UTF-16)的编码方式存储在内存中
3、 按照某种编码将数据写入目的地

本篇文章主要分为3个章节来介绍:
1、 Java Application 中的中文编解码
2、 Java web中的中文编解码分析
3、 JavaScript中的中文编解码分析

Java Application 中的中文编解码

开发环境是eclipse,文件编码都设置为了UTF-8。

我们直接在代码中硬编码,如下:

String str = “中国”;

System.out.println(str);

这个时候,控制台输出的结果是正确的,不会出现乱码。但如果采用这种方式:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

str = br.readLine();

System.out.println(str);

从eclipse的控制台中输入中文,再回显在控制台中,便会出现乱码。下面对这两种现象分析如下:

按照Java处理字符的三步走,因为eclipse中已经设置了文件编码是UTF-8,只要eclipse不出错,那么就可以肯定这个java源文件是UTF-8格式。

然后,利用eclipse来编译,编译后数据会议Unicode的格式存入字节码文件中。

最后,eclipse调用java命令输出,由于控制台的编码格式也是UTF-8,故而第一种方式不会出现乱码。

但是,如果不是硬编码而是从控制台输入中文,因为键盘的输入流的默认格式为系统默认编码,对中文操作系统而言就是GBK。这样便导致了GBK转UTF-8过程中出现了乱码。

Java web****中的中文编解码分析

Java Web开发过程中进场会遇到中文乱码的问题,比如:前台参数传输之服务端后乱码,服务端响应到达浏览器后乱码,等等。

首先看一下javaWeb开发中出现的各种编码:

1、  Jsp文件自身的编码

2、  Tomcat读取jsp文件时采用的编码

3、  Tomcat返回响应时采用的编码

4、  浏览器显示html时采用的编码

Jsp文件中会出现下面所示的编码指定方式:

<%@ page language=_“java”_ contentType=_“text/html; charset=UTF-8″_    pageEncoding=_“UTF-8″_%>

pageEncoding指的是改jsp文件自身采用的编码格式,这个编码要跟jsp文件的实际编码格式保持一致。contentType中的charset用来指定Tomcat返回响应时采用的编码,也是post方式提交参数的编码方式。Meta标签中的charset是在contentType未指定编码时采用的默认编码格式。

这里最常见的乱码出现在request.getParameter()过程中。这里分为GET方式和POST方式来分别分析。

1、  GET方式

首先,认识一下URL

Java开发中的编码问题总结

URL到底是以什么格式来编码呢?这要分为两种情形。

情形一:URL是在浏览器地址栏中输入的,该URL将会采用UTF-8来编码,注意是URL并不包括后面的Query String。实际上,这个Query String是采用系统默认编码GBK来编码的。

情形二:URL是通过页面中链接等类似方式产生的,这个Query String将会采用源页面的编码方式来编码。

Tomcat在接收到这样的URL后,默认采用ISO-8859-1来解码URL,包括Query String,这个编码可以通过设置Tomcat配置文件中的URIEncoding属性来改变。需要注意的是,这个编码参数只适用于GET方式提交的参数。

2、  POST方式

POST表单参数是通过http的body传递到服务器的。前面已经说过,表单项参数是采用contentType中的charset指定的编码格式进行编码的。服务器端也是用contentType中的charset指定的编码进行解码操作,所以一般不会出现乱码问题。这个编码我们可以通过request.setCharacterEncoding()来进行设置,该设置只对POST参数有效。注意,这个函数必须在第一次调用request.getParameter()之前使用。

GET和POST两种方式的不同表现使得处理起来比较麻烦。好在还存在一种解决方案,那就是设置Tomcat的参数useBodyEncodingForURI=true(注意,并不是对整个URI都采用BodyEncoding,只是应用于Query String而已)。这样,Tomcat便会用request.setCharacterEncoding()指定的编码来解析GET参数了。

JavaScript****中的中文编解码分析

使用URL进行参数传递时,可能会含有中文或者特殊字符,这样就会导致乱码问题。JavaScript对文字进行编码涉及3个函数:escape、encodeURI、encodeURIComponent,对应3个解码函数:unescape、decodeURI、decodeURIComponent。

escape:采用ISO Latin字符集对指定的字符串进行编码。所有的空格、标点、特殊字符以及其他非ASCII字符都被转化为%xx格式的字符编码。

不编码字符(69个):*、+、-、.、/、@、_、0-9、a-z、A-Z

encodeURI:把URI字符串采用UTF-8格式编码。

不编码字符(82个):!、#、$、&、’、(、)、,、:、;、=、?、~、*、+、-、.、/、@、_、0-9、a-z、A-Z

进行URL跳转时可以整体使用encodeURI,例如:

Location.href=encodeURI(“http://localhost:8080/query?floor=5楼&version=2”);

encodeURIComponent:与encodeURI类似,只是该方法将对更多的字符进行编码。

不编码字符(71个):!、’、(、)、~、*、-、.、_、0-9、a-z、A-Z

传递参数时需要使用encodeURIComponent,这样组合的URL才不会被#等特殊字符截断。

JavaScript编码后的参数,服务器端可以用URLDecoder.decode来解码。但是需要注意的是,Tomcat会自动先对URL做一次解码,但这次解码并非是使用URLDecoder.decode。针对这种情况一种方案就是在JavaScript中对参数进行两次encodeURIComponent编码。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
3年前
JS 苹果手机日期显示NaN问题
问题描述newDate("2019122910:30:00")在IOS下显示为NaN原因分析带的日期IOS下存在兼容问题解决方法字符串替换letdateStr"2019122910:30:00";datedateStr.repl
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这