JAVA中文乱码问题的分析与解决方案_刘瑞玲

JAVA中文乱码问题的分析与解决方案

刘瑞玲1 苟浩锋2 杜叔强1

(1.兰州工业高等专科学校软件工程系 甘肃兰州 730050; 2.

兰州市气象局 甘肃兰州 730020)

摘 要: Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要

有两方面,Java和JSP文件本身编译时产生的乱码问题和Java程序于其他媒介交互产生的乱码问题。

关键词:Java;中文乱码问题

中图分类号:[O244] 文献标识码:A 文章编号:1000-9795(2012)03-0403-01

一、引言

Java中文问题一直困扰着很多初学者,如果了解了Java系统的

中文问题原理,我们就可以对中文问题能够采取根本的解决之道。

Java总是根据操作系统的默认编码字符集来决定字符串的初

始编码,而且Java系统的输入和输出的都是采取操作系统的默认编

码。

因此,如果能统一Java系统的输入、输出和操作系统三者的编

码字符集合,将能够使Java系统正确处理和显示汉字。

二、中文乱码的由来

首先,Java(包括JSP)源文件中很可能包含有中文,而Java和

JSP源文件的保存方式是基于字节流的,如果Java和JSP编译成class

文件过程中,使用的编码方式与源文件的编码不一致,就会出现

乱码。基于这种乱码,建议在Java文件中尽量不要写中文(注释部

分不参与编译,写中文没关系),如果必须写的话,尽量手动带参

数-ecoding GBK或-ecoding gb2312编译;对于JSP,在文件头加

上<%@ page contentType="text/html;charset=GBK"%>或<%@ page

contentType="text/html;charset=gb2312"%>基本上就能解决这类乱码

问题。

本文要重点讨论的是第二类乱码,即Java程序与其他存储媒介

交互时产生的乱码。很多存储媒介,如数据库、文件、流等的存储

方式都是基于字节流的,Java程序与这些媒介交互时就会发生字符

(char)与字节(byte)之间的转换,在转换过程中使用的编码方式与字

节原有的编码不一致,很可能就会出现乱码。

三、中文乱码的解决方案

处理乱码问题最重要的就是保证转换时使用的编码方式和转换 前的编码机制一样,以下是针对不同问题的几种论述方案。

1.JSP和页面参数传递间的乱码

JSP获取页面参数时一般采用系统默认的编码方式,如

果页面参数的编码类型和系统默认的编码类型不一致,很可 能就会出现乱码。解决这类乱码问题的基本方法是在页面获 取参数之前,强制指定request获取参数的编码方式:request. setCharacterEncoding(“GBK”)或

request.setCharacterEncoding("gb2312")。如果在JSP将变量输出 到页面时出现了乱码,可以通过设置response.setContentType("text/ html;charset=GBK")或response.setContentType

("text/html;charset=gb2312")解决。如果不想在每个文件里都写 这样两句话,更简洁的办法是使用Servlet规范中的过虑器指定编 码,过滤器的在web.xml中的典型配置和主要代码如下: web.xml:

<filter>

<filter-name>CharacterEncodingFilter</filter-name>

<filter-class>net.vschool.web.CharacterEncodingFilter</filter- class>

<init-param>

<param-name>encoding</param-name>

<param-value>GBK</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>CharacterEncodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

CharacterEncodingFilter.java:

public class CharacterEncodingFilter implements Filter

{

protected String encoding = null;

public void init(FilterConfig filterConfig) throws ServletException {this.encoding = filterConfig.getInitParameter("encoding");} public void doFilter(ServletRequest request, ServletResponse

response, FilterChain chain) throws IOException, Servlet Exception {request.setCharacterEncoding(encoding);

response.setContentType("text/html;charset="+encoding);

chain.doFilter(request, response);

}

2.Java与数据库之间的乱码

大部分数据库都支持以unicode编码方式,所以解决Java与数据 库之间的乱码问题比较明智的方式是直接使用unicode编码与数据库

交互。很多数据库驱动自动支持unicode,如Microsoft的SQLServer驱 动。其他大部分数据库驱动,可以在驱动的url参数中指定,如如

mm的mysql驱动:jdbc:mysql://localhost/WEBCLDB?useUnicode=true& characterEncoding=GBK。

3.Java与文件/流之间的乱码

Java读写文件最常用的类是FileInputStream/FileOutputStream

和FileReader/FileWriter。其中FileInputStream和FileOutputStream是 基于字节流的,常用于读写二进制文件。读写字符文件建议使用 基于字符的FileReader和FileWriter,省去了字节与字符之间的转 换。但这两个类的构造函数默认使用系统的编码方式,如果文 件内容与系统编码方式不一致,可能会出现乱码。在这种情况 下,建议使用FileReader和FileWriter的父类:InputStreamReader/ OutputStreamWriter,它们也是基于字符的,但在构造函数中可 以指定编码类型:InputStreamReader(InputStream in, Charset cs)和 OutputStreamWriter (OutputStream out, Charset cs)。

4.其他理指标大部分为事后指标。

(二)建筑工程招标投标阶段安全管理

在招投标阶段的安全管理,重在审查的过程,在这点上,我国 的安全管理工作,做的还不到位。

因此,笔者认为,应多加学习国外发达国家的主动安全管理思 想,我国的安全管理存在被动性,所以,我们应该改变完善我国的 整个安全管理体系。

(三)建筑工程施工阶段安全管理

施工阶段,是安全管理的最重要阶段。在施工阶段,导致出现 安全问题的因素最多,而我国的安全管理工作落实的并不到位,体 制也不健全。

国外将项目管理理论和安全管理实践有机融合为一体,并将危 险源辨识、评价和控制作为安全管理中的核心。国外发达国家安全 管理软件的应用是比较完善的,这都是我国应该学习的地方。

(四)建筑工程使用阶段安全管理

工程竣工验收后便进入使用阶段,然而这个阶段也应该有相应 的安全管理,竣工验收并不代表安全管理工作的结束。而我国的安 全管理在使用阶段就停止了。

四、总结及建议

(一)建立完整的安全管理体系

针对包括建筑工程各个阶段的全过程,建立健全的安全管理体 系,做到企业、项目、施工现场三位一体的整体协同管理。

(二)加强运用信息化和IT技术进行安全管理信息系统开发

努力开发安全管理系统。以信息化的管理完成人力无法完成的 安全管理目标,简化安全管理的流程,加速安全信息在各个组织层 得传播,并进行安全知识的集成管理,实现高效率、高标准的建筑 工程安全管理工作。

(三)增强管理人员对安全管理的重视度

培养并提高管理人员以及工作人员的素质,做好安全知识的宣

传工作,提高管理人员的警惕性及重视程度。

(四)学习发达国家将项目管理理论和安全管理理论有机的融合

起来

将安全管理信息系统运用到建设项目管理系统中,充分利用项

目管理信息系统中的信息数据以及应用软件,达到建筑工程安全、

质量、进度等一体化的目的。从而保证建筑工程能以最佳的状态顺

利进行。

参考文献:

[ 1 ] 张 艳 芳 . 建 筑 安 全 管 理 工 作 分 析 及 探 索 [ J ] . 山 西 水

利,2008(4):90-91.

[ 2 ] 张高峰 . 建筑业安全事故的成因何在 [ J ] . 施工企业管

理,2006(6):60-61.

[3]张飞涟,王磊明.我国建筑安全事故原因探析及对策研究[J].建

筑安全,2006(2):11-12.

Discussion on safety management of building project

Peng Lin-hai

(School of Management, Guizhou University, Guiyang Guizhou,550025, China)

Abstract: With the rapid development of building trade, the personnel engaged in the building trade is increasing, the requirement of building safety

management is increasingly. This article elaborates and analyzes the current situation of building safety management in engineering, the causes of the

accident, and the differences of domestic and abroad safety management, draws the conclusions and put forward the corresponding proposals.

Key words: building engineering; safety accident; safety management

[责任编辑:陈怀民]

上面提到的方法应该能解决大部分乱码问题,如果在其他地

方还出现乱码,可能需要手动修改代码。解决Java乱码问题的关键

在于在字节与字符的转换过程中,必须知道原来字节或转换后的

字节的编码方式,转换时采用的编码必须与这个编码方式保持一

致。我们以前使用Resin服务器,使用smartUpload组件上传文件,

上传文件同时传递的中文参数获取没有乱码问题。当在Linux中把

Resin设置成服务后,上传文件同时的中文参数获取出现了乱码。

据后来分析smartUpload组件的源文件,因为文件上传采用的是字节

流的方式,里面包含的参数名称和值也是字节流的方式传递的。

smartUpload组件读取字节流后再将参数名称和值从字节流中解析出

来,问题就出现在smartUpload将字节流转换成字符串时采用了系统

默认的编码,而将Resin设置成服务后,系统默认的编码可能发生

了改变,因此出现了乱码。后来,我们更改了smartUpload的源文

件,增加了一个属性charset和setCharset(String)方法,将upload()方法

中提取参数语句: String value = new String(m_binArray, m_startData,

(m_endData - m_startData) + 1 );改成了String value = new String(m_

binArray, m_startData, (m_endData - m_startData) + 1, charset );终于解

决了这个乱码问题。

四、结束语

Java 语言内部采用 Unicode 编码 java 语言运行时需要将 Unicode

编码和对应的操作系统、浏览器、数据库的编码格式进行转换输入

和输出,在这个转换过程中,若有一步出错 就会出现中文乱码的

问题。对于中文乱码问题,只要找出是在哪一步出现了错误,以及

错误的原因,便可有针对性地解决中文乱码的问题。

参考文献:

[1]Bruce Eckel.Think in Java[M].New Jersey:Prentice Hall,1998.

[2]赵海廷.Java 程序设计教程[M].武汉:武汉大学出版社,2008.

[3]飞思科技产品研发中心.JSP 应用开发详解[M].北京:电子工

业出版社,2002.

The analysis and solutions of JAVA Chinese garbled problems

Liu Rui-ling

1

, Gou Hao-feng

2

, Du Shu-qiang

1

(1. Department of Software Engineering, Lanzhou Institute of Technology, Lanzhou Gansu, 730050, China;

2. Lanzhou Meteorological Bureau, Lanzhou Gansu,730020, China )

Abstract: The kernel of Java and class file is based on the unicode, this makes the Java program have good cross-platform, but it also brings about

some problems of Chinese characters. There are two reasons, Java and JSP file itself compiled generated when the garbage problem and Java programs in

other media interaction programming questions.

Key words: Java; Chinese garbled problems

[责任编辑:陈怀民]

(上接第403页)

 

第二篇:java中文乱码问题解决方案

Java中文问题一直困扰着很多初学者,如果了解了Java系统的中文问题原理,我们就可以对中文问题能够采取根本的解决之道。

最古老的解决方案是使用String的字节码转换,这种方案问题是不方便,我们需要破坏对象封装性,进行字节码转换。

还有一种方式是对J2EE容器进行编码设置,如果J2EE应用系统脱离该容器,则会发生乱码,而且指定容器配置不符合J2EE应用和容器分离的原

则。

在Java内部运算中,涉及到的所有字符串都会被转化为UTF-8编码来进行运算。那么,在被Java转化之前,字符串是什么样的字符集? Java总

是根据操作系统的默认编码字符集来决定字符串的初始编码,而且Java系统的输入和输出的都是采取操作系统的默认编码。

因 此,如果能统一Java系统的输入、输出和操作系统3者的编码字符集合,将能够使Java系统正确处理和显示汉字。这是处理Java系统汉字的

一个原则, 但是在实际项目中,能够正确抓住和控制住Java系统的输入和输出部分是比较难的。J2EE中,由于涉及到外部浏览器和数据库等,

所以中文问题乱码显得非 常突出。

J2EE应用程序是运行在J2EE容器中。在这个系统中,输入途径有很多种:一种是通过页面表单打包成请求 (request)发往服务器的;第二种

是通过数据库读入;还有第3种输入比较复杂,JSP在第一次运行时总是被编译成Servlet,JSP中常常包含 中文字符,那么编译使用javac时,

Java将根据默认的操作系统编码作为初始编码。除非特别指定,如在Jbuilder/eclipse中可以指定默 认的字符集。

输出途径也有几种:第一种是JSP页面的输出。由于JSP页面已经被编译成Servlet,那么在输出时,也将根据操作系统的默认编码来选择输出编

码,除非指定输出编码方式;还有输出途径是数据库,将字符串输出到数据库。

由此看来,一个J2EE系统的输入输出是非常复杂,而且是动态变化的,而Java是跨平台运行的,在实际编译和运行中,都可能涉及到不同的操

作系统,如果任由Java自由根据操作系统来决定输入输出的编码字符集,这将不可控制地出现乱码。

正是由于Java的跨平台特性,使得字符集问题必须由具体系统来统一解决,所以在一个Java应用系统中,解决中文乱码的根本办法是明确指定

整个应用系统统一字符集。

指定统一字符集时,到底是指定ISO8859_1 、GBK还是UTF-8呢?

(1)如统一指定为ISO8859_1,因为目前大多数软件都是西方人编制的,他们默认的字符集就是ISO8859_1,包括操作系统Linux和数据库MySQL

等。这样,如果指定Jive统一编码为ISO8859_1,那么就有下面3个环节必须把握:

开发和编译代码时指定字符集为ISO8859_1。

运行操作系统的默认编码必须是ISO8859_1,如Linux。

在JSP头部声明:。

(2)如果统一指定为GBK中文字符集,上述3个环节同样需要做到,不同的是只能运行在默认编码为GBK的操作系统,如中文Windows。

统一编码为ISO8859_1和GBK虽然带来编制代码的方便,但是各自只能在相应的操作系统上运行。但是也破坏了Java跨平台运行的优越性,只在

一定范围内行得通。例如,为了使得GBK编码在linux上运行,设置Linux编码为GBK。

那么有没有一种除了应用系统以外不需要进行任何附加设置的中文编码根本解决方案呢?

将Java/J2EE系统的统一编码定义为UTF-8。UTF-8编码是一种兼容所有语言的编码方式,惟一比较麻烦的就是要找到应用系统的所有出入口,然

后使用UTF-8去“结扎”它。

一个J2EE应用系统需要做下列几步工作:

开发和编译代码时指定字符集为UTF-8。JBuilder和Eclipse都可以在项目属性中设置。

使用过滤器,如果所有请求都经过一个Servlet控制分配器,那么使用Servlet的filter执行语句,将所有来自浏览器的请求(request)转换为

UTF-8,因为浏览器发过来的请求包根据浏览器所在的操作系统编码,可能是各种形式编码。关键一句:

request.setCharacterEncoding("UTF-8")。

网上有此filter的源码,Jdon框架源码中com.jdon.util.SetCharacterEncodingFilter

需要配置web.xml 激活该Filter。

在JSP头部声明:。

在Jsp的html代码中,声明UTF-8:

设定数据库连接方式是UTF-8。例如连接MYSQL时配置URL如下:

jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8

一般数据库都可以通过管理设置设定UTF-8

其他和外界交互时能够设定编码时就设定UTF-8,例如读取文件,操作XML等。

一、Java中文问题的由来

Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面,Java和JSP文件本身编译时产生的乱码问题和Java程序于其他媒介交互产生的乱码问题。

先Java(包括JSP)源文件中很可能包含有中文,而Java和JSP源文件的保存方式是基于字节流的,如果Java和JSP编译成class文件过程

中,使用的编码方式与源文件的编码不一致,就会出现乱码。基于这种乱码,建议在Java文件中尽量不要写中文(注释部分不参与编译,写中文没关系),如果

必须写的话,尽量手动带参数-ecoding GBK或-ecoding gb2312编译;对于JSP,在文件头加上<%

@ page contentType="text/html;charset=GBK"%>或<%@ page contentType=

"text/html;charset=gb2312"%>基本上就能解决这类乱码问题。

本文要重点讨论的是第二类乱码,即Java程序与其他存储媒介交互时产生的乱码。很多存储媒介,如数据库,文件,流等的存储方式都是基于字节流的,Java程序与这些媒介交互时就会发生字符(char)与字节(byte)之间的转换,具体情况如下:

从页面form提交数据到java程序 byte->char

从java程序到页面显示 char?>byte

从数据库到java程序 byte?>char

从java程序到数据库 char?>byte

从文件到java程序 byte->char

从java程序到文件 char->byte

从流到java程序 byte->char

从java程序到流 char->byte

如果在以上转换过程中使用的编码方式与字节原有的编码不一致,很可能就会出现乱码。

二、解决方法

前面已经提到了Java程序与其他媒介交互时字符和字节的转换过程,如果这些转换过程中容易产生乱码。解决这些乱码问题的关键在于确保转换时使用的编码方式与字节原有的编码方式保持一致,下面分别论述(Java或JSP自身产生的乱码请参看第一部分)。

1、JSP与页面参数之间的乱码

JSP

获取页面参数时一般采用系统默认的编码方式,如果页面参数的编码类型和系统默认的编码类型不一致,很可能就会出现乱码。解决这类乱码问题的基本方法是在页

面获取参数之前,强制指定request获取参数的编码方式:request.setCharacterEncoding("GBK")或

request.setCharacterEncoding("gb2312")。

如果在JSP将变量输出到页面时出现了乱码,可以通过设置

response.setContentType("text/html;charset=GBK")或response.setContentType ("text/html;charset=gb2312")解决。

如果不想在每个文件里都写这样两句话,更简洁的办法是使用Servlet规范中的过虑器指定编码,过滤器的在web.xml中的典型配置和主要代码如下:

web.xml:

<filter>

<filter-name>CharacterEncodingFilter</filter-name>

<filter-class>net.vschool.web.CharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>GBK</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>CharacterEncodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

CharacterEncodingFilter.java:

public class CharacterEncodingFilter implements Filter

{

protected String encoding = null;

public void init(FilterConfig filterConfig) throws ServletException

{

this.encoding = filterConfig.getInitParameter("encoding");

}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException

{

request.setCharacterEncoding(encoding);

response.setContentType("text/html;charset="+encoding);

chain.doFilter(request, response);

}

}

2、Java与数据库之间的乱码

部分数据库都支持以unicode编码方式,所以解决Java与数据库之间的乱码问题比较明智的方式是直接使用unicode编码与数据库交互。很多数据

库驱动自动支持unicode,如Microsoft的SQLServer驱动。其他大部分数据库驱动,可以在驱动的url参数中指定,如如mm的

mysql驱动:jdbc:mysql://localhost/WEBCLDB?useUnicode=true&

characterEncoding=GBK。

3、Java与文件/流之间的乱码

Java读写文件最常用的类是

FileInputStream/FileOutputStream和FileReader/FileWriter。其中FileInputStream 和FileOutputStream是基于字节流的,常用于读写二进制文件。读写字符文件建议使用基于字符的FileReader和

FileWriter,省去了字节与字符之间的转换。但这两个类的构造函数默认使用系统的编码方式,如果文件内容与系统编码方式不一致,可能会出现乱码。

在这种情况下,建议使用FileReader和FileWriter的父类:

InputStreamReader/OutputStreamWriter,它们也是基于字符的,但在构造函数中可以指定编码类型:

InputStreamReader(InputStream in, Charset cs) 和OutputStreamWriter

(OutputStream out, Charset cs)。

4、其他

上面提到的方法应该能解决大部分乱码问题,如果在

其他地方还出现乱码,可能需要手动修改代码。解决Java乱码问题的关键在于在字节与字符的转换过程中,你必须知道原来字节或转换后的字节的编码方式,转

换时采用的编码必须与这个编码方式保持一致。我们以前使用Resin服务器,使用smartUpload组件上传文件,上传文件同时传递的中文参数获取没

有乱码问题。当在Linux中把Resin设置成服务后,上传文件同时的中文参数获取出现了乱码。这个问题困扰了我们很久,后来我们分析

smartUpload组件的源文件,因为文件上传采用的是字节流的方式,里面包含的参数名称和值也是字节流的方式传递的。smartUpload组件读

取字节流后再将参数名称和值从字节流中解析出来,问题就出现在smartUpload将字节流转换成字符串时采用了系统默认的编码,而将Resin设置成

服务后,系统默认的编码可能发生了改变,因此出现了乱码。后来,我们更改了smartUpload的源文件,增加了一个属性charset和

setCharset(String)方法,将upload()方法中提取参数语句:

String value = new String(m_binArray, m_startData, (m_endData - m_startData) + 1 ); 改成了

String value = new String(m_binArray, m_startData, (m_endData - m_startData) + 1, charset );

终于解决了这个乱码问题。

相关推荐