java万能编码转换_java编码转换的详细过程

常见的JAVA程序包括以下类别:

*直接在console上运行的类(包括可视化界面的类)

*JSP代码类(注:JSP是Servlets类的变型)

*Servelets类

*EJB类

*其它不可以直接运行的支持类

这些类文件中,都有可能含有中文字符串,并且常用前三类JAVA程序和用户直接交互,用于输出和输入字符,如:在JSP和Servlet中得到客户端送来的字符,这些字符也包括中文字符。无论这些JAVA类的作用如何,这些JAVA程序的生命周期都是这样的:

*编程人员在一定的操作系统上选择一个合适的编辑软件来实现源程序代码并以.java扩展名保存在操作系统中,例如我们在中文win2k中用记事本编辑一个java源程序;

*编程人员用JDK中的javac.exe来编译这些源代码,形成.class类(JSP文件是由容器调用JDK来编译的);

*直接运行这些类或将这些类布署到WEB容器中去运行,并输出结果。

那么,在这些过程中,JDK和JVM是如何将这些文件如何编码和解码并运行的呢?

这里,以中文win2k操作系统为例说明JAVA类是如何来编码和被解码的。

第一步,我们在中文win2k中用编辑软件如记事本编写一个Java源程序文件(包括以 上五类JAVA程序),程序文件在保存时默认采用了操作系统默认支持GBK编码格式(操作系统默认支持的格式为file.encoding格式)形成了一 个.java文件,也即,java程序在被编译前,我们的JAVA源程序文件是采用操作系统默认支持的file.encoding编码格式保存的, java源程序中含有中文信息字符和英文程序代码;要查看系统的file.encoding参数,可以用以下代码:

public class ShowSystemDefaultEncoding {

public static void main(String[] args) {

String encoding = System.getProperty("file.encoding");

System.out.println(encoding);

}}

第二步,我们用JDK的javac.exe文件编译我们的Java源程序,由于JDK是 国际版的,在编译的时候,如果我们没有用-encoding参数指定我们的JAVA源程序的编码格式,则javac.exe首先获得我们操作系统默认采用 的编码格式,也即在编译java程序时,若我们不指定源程序文件的编码格式,JDK首先获得操作系统的file.encoding参数(它保存的就是操作 系统默认的编码格式,如WIN2k,它的值为GBK),然后JDK就把我们的java源程序从file.encoding编码格式转化为JAVA内部默认 的UNICODE格式放入内存中。然后,javac把转换后的unicode格式的文件进行编译成.class类文件,此时.class文件是 UNICODE编码的,它暂放在内存中,紧接着,JDK将此以UNICODE编码的编译后的class文件保存到我们的操作系统中形成我们见到的. class文件。对我们来说,我们最终获得的.class文件是内容以UNICODE编码格式保存的类文件,它内部包含我们源程序中的中文字符串,只不过 此时它己经由file.encoding格式转化为UNICODE格式了。

这一步中,对于JSP源程序文件是不同的,对于JSP,这个过程是这样的:即WEB容器 调用JSP编译器,JSP编译器先查看JSP文件中是否设置有文件编码格式,如果JSP文件中没有设置JSP文件的编码格式,则JSP编译器调用JDK先 把JSP文件用JVM默认的字符编码格式(也即WEB容器所在的操作系统的默认的file.encoding)转化为临时的Servlet类,然后再把它 编译成UNICODE格式的class类,并保存在临时文件夹中。如:在中文win2k上,WEB容器就把JSP文件从GBK编码格式转化为 UNICODE格式,然后编译成临时保存的Servlet类,以响应用户的请求。

第三步,运行第二步编译出来的类,分为三种情况:

A、 直接在console上运行的类

B、 EJB类和不可以直接运行的支持类(如JavaBean类)

C、 JSP代码和Servlet类

D、 JAVA程序和数据库之间

下面分这四种情况来看。

A、直接在console上运行的类

这种情况,运行该类首先需要JVM支持,即操作系统中必须安装有JRE。运行过程是这样 的:首先java启动JVM,此时JVM读出操作系统中保存的class文件并把内容读入内存中,此时内存中为UNICODE格式的class类,然后 JVM运行它,如果此时此类需要接收用户输入,则类会默认用file.encoding编码格式对用户输入的串进行编码并转化为unicode保存入内存 (用户可以设置输入流的编码格式)。程序运行后,产生的字符串(UNICODE编码的)再回交给JVM,最后JRE把此字符串再转化为 file.encoding格式(用户可以设置输出流的编码格式)传递给操作系统显示接口并输出到界面上。

以上每一步的转化都需要正确的编码格式转化,才能最终不出现乱码现象。

B、EJB类和不可以直接运行的支持类(如JavaBean类)

由于EJB类和不可以直接运行的支持类,它们一般不与用户直接交互输入和输出,它们常常 与其它的类进行交互输入和输出,所以它们在第二步被编译后,就形成了内容是UNICODE编码的类保存在操作系统中了,以后只要它与其它的类之间的交互在 参数传递过程中没有丢失,则它就会正确的运行。

C、JSP代码和Servlet类

经过第二步后,JSP文件也被转化为Servlets类文件,只不过它不像标准的Servlets一校存在于classes目录中,它存在于WEB容器的临时目录中,故这一步中我们也把它做为Servlets来看。

对于Servlets,客户端请求它时,WEB容器调用它的JVM来运行 Servlet,首先,JVM把Servlet的class类从系统中读出并装入内存中,内存中是以UNICODE编码的Servlet类的代码,然后 JVM在内存中运行该Servlet类,如果Servlet在运行的过程中,需要接受从客户端传来的字符如:表单输入的值和URL中传入的值,此时如果程 序中没有设定接受参数时采用的编码格式,则WEB容器会默认采用ISO-8859-1编码格式来接受传入的值并在JVM中转化为UNICODE格式的保存 在WEB容器的内存中。Servlet运行后生成输出,输出的字符串是UNICODE格式的,紧接着,容器将Servlet运行产生的UNICODE格式 的串(如html语法,用户输出的串等)直接发送到客户端浏览器上并输出给用户,如果此时指定了发送时输出的编码格式,则按指定的编码格式输出到浏览器 上,如果没有指定,则默认按ISO-8859-1编码发送到客户的浏览器上。

D、Java程序和数据库之间

对于几乎所有数据库的JDBC驱动程序,默认的在JAVA程序和数据库之间传递数据都是 以ISO-8859-1为默认编码格式的,所以,我们的程序在向数据库内存储包含中文的数据时,JDBC首先是把程序内部的UNICODE编码格式的数据 转化为ISO-8859-1的格式,然后传递到数据库中,在数据库保存数据时,它默认即以ISO-8859-1保存,所以,这是为什么我们常常在数据库中 读出的中文数据是乱码。

3、分析常见的JAVA中文问题几个必须清楚的原则

首先,经过上面的详细分析,我们可以清晰地看到,任何JAVA程序的生命期中,其编码转换的关键过程是在于:最初编译成class文件的转码和最终向用户输出的转码过程。

其次,我们必须了解JAVA在编译时支持的、常用的编码格式有以下几种:

*ISO-8859-1,8-bit, 同8859_1,ISO-8859-1,ISO_8859_1等编码

*Cp1252,美国英语编码,同ANSI标准编码

*UTF-8,同unicode编码

*GB2312,同gb2312-80,gb2312-1980等编码

*GBK , 同MS936,它是gb2312的扩充

及其它的编码,如韩文、日文、繁体中文等。同时,我们要注意这些编码间的兼容关体系如下:

unicode和UTF-8编码是一一对应的关系。GB2312可以认为是GBK的子集,即GBK编码是在gb2312上扩展来的。同时,GBK编码包含了20902个汉字,编码范围为:0x8140-0xfefe,所有的字符可以一一对应到UNICODE2.0中来。

再次,对于放在操作系统中的.java源程序文件,在编译时,我们可以指定它内容的编码格式,具体来说用-encoding来指定。注意:如果源程序中含有中文字符,而你用-encoding指定为其它的编码字符,显然是要出错的。用- encoding指定源文件的编码方式为GBK或gb2312,无论我们在什么系统上编译含有中文字符的JAVA源程序都不会有问题,它都会正确地将中文转化为UNICODE存储在class文件中。

然后,我们必须清楚,几乎所有的WEB容器在其内部默认的字符编码格式都是以ISO- 8859-1为默认值的,同时,几乎所有的浏览器在传递参数时都是默认以UTF-8的方式来传递参数的。所以,虽然我们的Java源文件在出入口的地方指 定了正确的编码方式,但其在容器内部运行时还是以ISO-8859-1来处理的。

4、中文问题的分类及其建议最优解决办法

了解以上JAVA处理文件的原理之后,我们就可以提出了一套建议最优的解决汉字问题的办法。

我们的目标是:我们在中文系统中编辑的含有中文字符串或进行中文处理的JAVA源程序经编译后可以移值到任何其它的操作系统中正确运行,或拿到其它操作系统中编译后能正确运行,能正确地传递中文和英文参数,能正确地和数据库交流中英文字符串。

我们的具体思路是:在JAVA程序转码的入口和出口及JAVA程序同用户有输入输出转换的地方限制编码方法使之正确即可。

具体解决办法如下:

1、 针对直接在console上运行的类

对于这种情况,我们建议在程序编写时,如果需要从用户端接收用户的可能含有中文的输入或含有中文的输出,程序中应该采用字符流来处理输入和输出,具体来说,应用以下面向字符型节点流类型:

对文件:FileReader,FileWrieter

其字节型节点流类型为:FileInputStream,FileOutputStream

对内存(数组):CharArrayReader,CharArrayWriter

其字节型节点流类型为:ByteArrayInputStream,ByteArrayOutputStream

对内存(字符串):StringReader,StringWriter

对管道:PipedReader,PipedWriter

其字节型节点流类型为:PipedInputStream,PipedOutputStream

同时,应该用以下面向字符型处理流来处理输入和输出:

BufferedWriter,BufferedReader

其字节型的处理流为:BufferedInputeStream,BufferedOutputStream

InputStreamReader,OutputStreamWriter

其字节型的处理流为:DataInputStream,DataOutputStream

其中InputStreamReader和InputStreamWriter用于将字节流按照指定的字符编码集转换到字符流,如:

InputStreamReader in = new InputStreamReader(System.in,"GB2312");

OutputStreamWriter out = new OutputStreamWriter (System.out,"GB2312");

例如:采用如下的示例JAVA编码就达到了要求:

//Read.java

import java.io.*;

public class Read {

public static void main(String[] args) throws IOException {

String str = "/n中文测试,这是内部硬编码的串"+"/ntest english character";

String strin= "";

BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in,"gb2312")); //设置输入接口按中文编码

BufferedWriter stdout = new BufferedWriter(new OutputStreamWriter(System.out,"gb2312")); //设置输出接口按中文编码

stdout.write("请输入:");

stdout.flush();

strin = stdin.readLine();

stdout.write("这是从用户输入的串:"+strin);

stdout.write(str);

stdout.flush();

}}

同时,在编译程序时,我们用以下方式来进行:

javac -encoding gb2312 Read.java

2、 针对EJB类和不可以直接运行的支持类(如JavaBean类)

由于这种类它们本身被其它的类调用,不直接与用户交互,故对这种类来说,我们的建议的处理方式是内部程序中应该采用字符流来处理程序内部的中文字符串(具体如上面一节中一样),同时,在编译类时用-encoding gb2312参数指示源文件是中文格式编码的即可。

3、 针对Servlet类

针对Servlet,我们建议用以下方法:

在编译Servlet类的源程序时,用-encoding指定编码为GBK或 GB2312,且在向用户输出时的编码部分用response对象的setContentType("text/html;charset=GBK"); 或gb2312来设置输出编码格式,同样在接收用户输入时,我们用request.setCharacterEncoding("GB2312");这样 无论我们的servlet类移植到什么操作系统中,只有客户端的浏览器支持中文显示,就可以正确显示。如下是一个正确的示例:

//HelloWorld.java

package hello;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class HelloWorld extends HttpServlet

{

public void init() throws ServletException { }

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException

{

request.setCharacterEncoding("GB2312"); //设置输入编码格式

response.setContentType("text/html;charset=GB2312"); //设置输出编码格式

PrintWriter out = response.getWriter(); //建议使用PrintWriter输出

out.println("Hello World! This is created by Servlet!测试中文!");

}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException

{

request.setCharacterEncoding("GB2312"); //设置输入编码格式

response.setContentType("text/html;charset=GB2312"); //设置输出编码格式

String name = request.getParameter("name");

String id = request.getParameter("id");

if(name==null) name="";

if(id==null) id="";

PrintWriter out = response.getWriter(); //建议使用PrintWriter输出

out.println("你传入的中文字串是:" + name);

out.println("你输入的id是:" + id);

}

public void destroy() { }

请用javac -encoding gb2312 HelloWorld.java来编译此程序。

4、 JAVA程序和数据库之间

为避免JAVA程序和数据库之间数据传递出现乱码现象,我们建议采用以下最优方法来处理:

1、 对于JAVA程序的处理方法按我们指定的方法处理。

2、 把数据库默认支持的编码格式改为GBK或GB2312的。

如:在mysql中,我们可以在配置文件my.ini中加入以下语句实现:

在[mysqld]区增加:

default-character-set=gbk

并增加:

[client]

default-character-set=gbk

在SQL Server2K中,我们可以将数据库默认的语言设置为Simplified Chinese来达到目的。

5、 针对JSP代码

由于JSP是在运行时,由WEB容器进行动态编译的,如果我们没有指定JSP源文件的编码格式,则JSP编译器会获得服务 器操作系统的file.encoding值来对JSP文件编译的,它在移植时最容易出问题,如在中文win2k中可以很好运行的jsp文件拿到英文 linux中就不行,尽管客户端都是一样的,那是因为容器在编译JSP文件时获取的操作系统的编码不同造成的(在中文wink中的 file.encoding和在英文Linux中file.encoding是不同的,且英文Linux的file.encoding对中文不支持,所以 编译出来的JSP类就会有问题)。网络上讨论的大多数是此类问题,多是因为JSP文件移植平台时不能正确显示的问题,对于这类问题,我们了解了JAVA中 程序编码转换的原理,解决起来就容易多了。我们建议的解决办法如下:

1、我们要保证JSP向客户端输出时是采用中文编码方式输出的,即无论如何我们首先在我们的JSP源代编中加入以下一行:

2、为了让JSP能正确获得传入的参数,我们在JSP源文件头加入下面一句:

3、为了让JSP编译器能正确地解码我们的含有中文字符的JSP文件,我们需要在JSP源文件中指定我们的JSP源文件的编码格式,具体来说,我们在JSP源文件头上加入下面的一句即可:

这是JSP规范2.0新增加的指令。

我们建

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/566483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java里怎么存入数据并进行排序_Java数据结构之排序---插入排序

插入排序的基本介绍:插入排序是对想要排序的序列以插入的方式寻找该元素的适当的位置,从而达到排序的目的。插入排序的基本思想:把n个待排序的元素看成一个有序表和一个无序表,开始时,有序表只有一个元素(整个序列的第…

db h2 数据类型_H2Database数据类型

标签:整数(INT)INT | INTEGER | MEDIUMINT | INT4 | SIGNED值的范围为: -2147483648 到 2147483647.对应到Java类型: java.lang.Integer.例如:INT布尔型(BOOLEAN)BOOLEAN| BIT | BOOL可能的值为: TRUE 和 FALSE。对应到…

etmvc mysql乱码_etmvc中集成spring使用druid连接池

etmvc中ActiveRecord(下称AR)在使用上可以独立使用,其数据库的连接信息通过activerecord.properties进行配置,具体如下:domain_base_classcom.et.ar.ActiveRecordBasecom.et.ar.ActiveRecordBase.driver_classcom.mysql.jdbc.Drivercom.et.ar…

java ftp读取文件内容_java读取ftp中TXT文件的案例

最近在开发关于java读取ftp中TXT文件,其中有些坑踩了一下,再次做个记录1、读取文件时我会根据文件名称去生成数据库表,oracle数据库对于表名的长度是有限制的,最多30个字符2、对于多个文件的ftp的读取,每次获取文件后再…

java sql server 2016_SQL server 2016 安装步骤

1.进入安装中心:可以参考硬件和软件要求、可以看到一些说明文档2.选择全新安装模式继续安装3.输入产品秘钥:这里使用演示秘钥进行4.在协议中,点击同意,并点击下一步按钮,继续安装5.进入全局规则检查项,这里…

java resource file_Java 获取Resource目录下的文件解决办法

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼Java 获取Resource目录下的 文件有两种方式:Java代码中的类,要获取Resource资源 文件目录 下文件绝对路径寻址注意这个 / 址的是根 目录 ,用绝对路径,可能会出现的问题是,…

java中有哪些锁_Java中有哪些锁?

1.公平锁 / 非公平锁2.可重入锁 / 不可重入锁3.独享锁 / 共享锁4.互斥锁 / 读写锁5.乐观锁 / 悲观锁6.分段锁7.偏向锁 / 轻量级锁 / 重量级锁8.自旋锁一、公平锁 / 非公平锁公平锁公平锁是指多个线程按照申请锁的顺序来获取锁。非公平锁非公平锁是指多个线程获取锁的顺序并不是…

java中对象类型转换_Java中的对象的类型转换介绍(附代码)

本篇文章给大家带来的内容是关于Java中的对象的类型转换介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。向上转型:子类对象转为父类,父类可以是接口。公式:Father f new Son(…

java中的single_解析java泛型(一)

对于我们java中的泛型,可能很多人知道怎么使用并且使用的还不错,但是我认为想要恰到好处的使用泛型,还是需要深入的了解一下它的各种概念和内部原理。本文将尽可能的囊括java泛型中的重要的概念。主要内容如下:泛型的定义及为什么…

java面板中添加面板_如何把窗体加入面板中 java

展开全部一般来说,我们常把JPanel[面板]放到JFrame窗体中但是也有一种内部窗体JInternalFrame ,可以放到其他的容器JDesktopPane里,效果图e69da5e887aa62616964757a686964616f31333363373731如下代码如下import java.awt.*;import java.awt.event.*;import java.beans.Property…

mysql 如果存在修改_mysql如存在并发修改可能,一定要注意保证数据一致性

近日,因人员调整接手了一个其他部门负责的项目。随后发现其中的很多关键环节是没有考虑mysql并发操作的,现列出存在的一例问题 并分享如何解决的。问题描述:用户账户余额转移赠送 (用户A将自己的账户剩余金额赠送给用户B),同一时刻还可能存在…

python prt_Python中的self

self代表类的实例,而非类。实例来说明Python1234567classTest:defprt(self):print(self)print(self.__class__)tTest()t.prt()执行结果如下Python12从上面的例子中可以很明显的看出,self代表的是类的实例。而self.class则指向类。self不必非写成self有很…

微信对账单 java_微信支付对账,你是如何处理的?

支付对账,即检查第三方支付与数据库中账单是否一一对应,涉及到微信对账单的处理,成功时,微信账单接口返回数据以文本表格的方式返回,第一行为表头,后面各行为对应的字段内容,字段内容跟查询订单…

java技术文章在哪里看呢_谈论Java技术似乎无处不在,但究竟是什么呢?文章末尾有福利...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼谈论Java技术似乎无处不在,但究竟是什么呢?下面的部分将解释Java技术如何既是一种编程语言,又是一种平台,并概述这种技术可以为您做些什么。Java编程语言是一种高级语言,可…

java中常用的关键字_java中的常用的关键字

在java编程过程中,会经常写到一些关键字,但是对于他们应用的方式其实一直是模仿状态,并没有很实质的去了解,为什么要这么用,导致程序不能优化,或者出现了bug不明所以,因而再详细的去重温了一下各…

java如何处理灰度图片_Java图片的灰度处理方法

通过看网上各种大牛的总结,和自己亲身测试总结一下Java图片的灰度处理方法(1)我们熟知的图片中的像素点有RGB值。(2)图片灰度化的方式大概分为四种,第一种是最大值法(取颜色RGB中的最大值作为灰度值);第二种是最小值法(取颜色RGB的最小值作为…

java多项式和_在Java中查找多项式的根

小编典典请找到以下相同的示例示例public class PolynomialRootFinder {/*** * Given a set of polynomial coefficients, compute the roots of the polynomial. Depending on* the polynomial being considered the roots may contain complex number. When complex numbers …

java7 nio2 新特性_JDK7新特性,你知道几个?

前言之前学习的过程中,每天都是老师说这个是JDK7以后可以使用,那个是JDK8以后可以使用,每天都记的很混乱,今天专门忙里偷闲,归拢整理下JDK7的新特性,对于JDK的新特性,后期会进行整理更新&#x…

java jsp校验提示信息_java Jquery表单校验代码jsp页面

jsp.file欢迎注册EasyMall/* 注册表单的js校验 */var formObj {/* 检查输入项是否为空 */"checkNull" : function(name, msg){var value $("input[name"name"]").val().trim();//清空之前的提示消息formObj.setMsg(name, "");if(val…

错误处理方法 java_JAVA常见错误处理方法 和 JVM内存结构

OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏;二是调整JVM启动参数增大内存。OutOfMemoryError有好几种情况,每次遇到这个错误时…