当前位置: 首页 > news >正文

JAVA基础:Java多语言编码问题解析

  1、Java编译器在对源文件编译前,会先把源文件转换为unicode编码,因为这个原因,我们在编译时一定要把源文件用的是什么编码方式正确无误的”告诉”编译器。

  例如:我们的源文件是以UTF-8的方式保存的,而在编译时却把它当作是用GBK方式保存的,这样编译器就会按照GBK->Unicode的编码转换方法对源文件进行转换,然后再编译,这样当然会出错,实际上编译器应当按照UTF-8->Unicode的编码转换方法来对源文件进行转换。

  a.对于控制台程序,编译器会把源文件看作是由系统默认的编码类型来编码的(系统默认的编码类型取决于在控制面板区域设置里的配置,中文win2k下通常是GBK),也可以使用-encoding参数来设置,如:javac -encoding UTF-8,这样编译器就会把源文件看作是用UTF-8编码的(这只是告诉编译器源文件的编码类型,而不是对源文件转码)。在各种语言的平台上只要在编译用时-encoding指定与源文件的编码相同的编码方式,就不会存在国际化的问题了。

  b.对于JSP,编译器则会根据设定的字符集来判断JSP文件使用的是什么编码方式,进而将其转换成unicode后进行编译;若JSP中未指定,编译器则会把JSP文件看作是按照系统默认的编码来保存的。在JSP2.0里新增了一个指令来通知编译器这个源文件所使用的编码方式。

  2、在处理输入输出时,注意设置输入流和输出流的编码类型与用户输入时和输出设备显示时采用的编码方式一致。

  由于JRE在处理输入输出时会将输入或输出的内容进行编码转换,对于输入会转换为unicode后再送入,因此要正确的匹配实际输入内容的编码方式和告知JRE的编码方式,对于输出,会由unicode转换为其他的编码再送出程序,因此要正确匹配输出设备显示时用的编码方式和告知JRE的编码方式。

  例如:程序中设置输入流的编码是new InputStreamReader(System.in,"GB2312");而程序运行后用户输入时用了繁体中文的输入法,输入了BIG5编码的内容,这样JRE把BIG5编码的内容当作GB2312的进行了GB2312->unicode的编码转换,这样转换后的结果显然不是用户想要输入的内容了。

  默认情况下,JRE会把输入输出的内容当作是按照系统默认编码方式编码的。

  3、在Servlet中,除了一定要把源文件用的是什么编码方式正确无误的”告诉”编译器外,还要注意实际提交的URL数据、表单数据的编码格式和request中声明的编码格式一致。

  客户端浏览器在通过表单和URL提交数据时,容器和JVM会将request中的数据看作是按照request所声明的编码方式来编码的,将数据由这种编码方式转换为unicode后再送入servlet(实际上容器会先将request中的数据转为一种中间编码方式,具体根据容器的配置而定,再由JVM由这种中间方式转换为unicode,通常这种中间格式是ISO)。servlet输出的unicode数据会由容器根据response中声明的编码方式进行转换,再送到客户端浏览器上。

  在接收客户端输入时,用request.setCharacterEncoding()声明请求中数据的编码方式。

  在向客户端输出时用response.setContentType("text/html;charset=");声明响应的数据的编码方式,告知浏览器以哪种编码方式显示。

  4、在JSP中,由于JSP本就会被JSP编译器编译为servlet来运行,因此情况与servlet相同。

  这两个JSP指令声明了请求和响应的编码方式。

  只要确保URL参数或表单中数据的编码方式和所声明的编码方式一致,再通过告知JSP编译器本JSP文件采用的编码方式及含有哪种字符,即可解决JSP的字符编码问题。

  这里是一个具体的例子:

  现在因为浏览器对UTF-8的支持,我们可以通过在源文件、请求、响应中都使用unicode编码方式,来轻松达到处理国际化和字符编码问题的目标。

  以我们使用的tomcat4.1.2为例,过程如下:

  1、编写JSP页面时:在每个JSP页面在页首都要增加一行:

  在编辑JSP页面时,一定要确保JSP文件以unicode的方式保存,目前几乎所有的编辑器都有以unicode编码保存或将文件内容转换成unicode的功能。

  2、增加一个用来声明request的CharacterEncoding的类SetCharacterEncodingFilter.java;

  SetCharacterEncodingFilter的这个类主要的作用就是:把request在从页面刚提交到server端的时候的encoding声明为我们想要的encoding,通过调用request的方法setCharacterEncoding (String encoding) 来改变,这样可以使request的从客户端传过来的时候,按我们在web.xml (在第二点可以讲到) 中配置的encoding来对提交的数据编码。

  3、修改web.xml文件,配置一个filter来过滤全部url请求,通过第二步中的类,声明所有url请求的编码类型未UTF-8。

  在web.xml文件中加上以下这段:

  

<filter-name></filter-name>Set Character Encoding
<filter-class></filter-class>org.kyle.web.sample.SetCharacterEncodingFilter
<init-param></init-param>
<param-name></param-name> encoding
<param-value></param-value> UTF-8


<filter-name></filter-name>Set Character Encoding
<url-pattern></url-pattern>/*

  在上面这段文字中“org.kyle.web.sample.SetCharacterEncodingFilter”指定步骤2中的类的位置,“ UTF-8”指定我们希望声明的request的编码类型,“/*”指定这个filter的适用范围(这里指的是全部url请求)。

  同时注意二个问题:

  1:servlet的版本必需是支持request.setCharacterEncoding(String encoding)这个方法才行,也就是在serlvert2.3以上。

  2:控制面板区域设置的当前代码页属性必需设定为"936 (GBK)",如果是"437(OEM-United States)"它处理文字的时候是8-bit,而中文和日文等是16-bit。所以在显示和处理时它把中文的前8位给截掉,这样就会出现乱码问题。

  附:SetCharacterEncodingFilter源文件

  

package org.kyle.web.sample;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
public class SetCharacterEncodingFilter implements Filter
{
/**
* The default character encoding to set for requests that pass through
* this filter.
*/
protected String encoding = null;
/**
* The filter configuration object we are associated with. If this value
* is null, this filter instance is not currently configured.
*/
protected FilterConfig filterConfig = null;


/**
* Should a character encoding specified by the client be ignored?
*/
protected boolean ignore = true;

/**
* Take this filter out of service.
*/
public void destroy()
{
this.encoding = null;
this.filterConfig = null;
}

/**
* Select and set (if specified) the character encoding to be used to
* interpret request parameters for this request.
*
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException
{

// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null))
{
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}

// Pass control on to the next filter
chain.doFilter(request, response);
}


/**
* Place this filter into service.
*
* @param filterConfig The filter configuration object
*
*encoding
* UTF-8
*
*/
public void init(FilterConfig filterConfig) throws ServletException
{
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}

/**
* Select an appropriate character encoding to be used, based on the
* characteristics of the current request and/or filter initialization
* parameters. If no character encoding should be set, return
* null.
*


* The default implementation unconditionally returns the value configured
* by the encoding initialization parameter for this
* filter.
*
* @param request The servlet request we are processing
*/
protected String selectEncoding(ServletRequest request)
{
return (this.encoding);
}
}

相关文章:

  • win10 外接usb摄像头_win10系统外接usb摄像头怎么打开
  • formatnumber js_js组件-js插件-jquery插件-数字或金额格式化
  • 搭建一个只在光盘或U盘上跑的小型LINUX系统
  • 浪潮服务器安装系统centos7_2288H V5 服务器安装centos7.4系统过程中无法启动图形界面安装...
  • ZT- 100年前的人蚁大战
  • mysql tokudb编译安装_mysql之Tokudb引擎安装
  • 领域驱动设计注释版已经出版
  • asp mysql分页_asp+mysql分页_MySQL
  • mysql limit 重复_mysql limit 翻页数据重复的问题
  • BPEL中的partnerlink和partnerlinktype
  • jdbc连接mysql的步骤_JDBC链接数据库的几个步骤
  • 介绍一种全新的哲学思想
  • linux mysql 导入数据库脚本_思维导图学 Linux Shell攻略之干货篇 mysql数据库脚本管理系统...
  • 哲学作为一门学说的可能
  • 批处理修改mysql密码_批处理脚本一键重置mysql的root密码
  • .pyc 想到的一些问题
  • 2017届校招提前批面试回顾
  • IOS评论框不贴底(ios12新bug)
  • python 装饰器(一)
  • SpringCloud集成分布式事务LCN (一)
  • Vue2 SSR 的优化之旅
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 再次简单明了总结flex布局,一看就懂...
  • 正则表达式
  • Python 之网络式编程
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​Linux·i2c驱动架构​
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • #pragma预处理命令
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (pojstep1.1.2)2654(直叙式模拟)
  • (笔试题)合法字符串
  • (定时器/计数器)中断系统(详解与使用)
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (四)库存超卖案例实战——优化redis分布式锁
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • .apk文件,IIS不支持下载解决
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .net 托管代码与非托管代码
  • @ComponentScan比较
  • @Import注解详解
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798
  • [2669]2-2 Time类的定义
  • [ACM] hdu 1201 18岁生日
  • [ACTF2020 新生赛]Include
  • [DevEpxress]GridControl 显示Gif动画
  • [element-ui] el-dialog 中的内容没有预先加载,因此无法获得内部元素的ref 的解决方案
  • [Excel VBA]单元格区域引用方式的小结
  • [JavaWeb学习] idea新建web项目