[个人总结]java中处理乱码问题个人总结
java乱码的问题的可谓是老生常谈了,自从接触java以来,就不断地与中文乱码的问题打交道,最近的参与的报表工具开发中,遇到的乱码问题更是让人头疼,随着项目工作的进度,自己总结了一下处理乱码的心得,在这里与大家一起分享一下。
Java的内核以及class文件都是采用的unicode的编码,这样java程序就具有了很好的跨平台性,随之也就带来了乱码的问题的麻烦。出现乱码的问题原因主要有两个方面Java及JSP文件本身编译时产生的乱码和Java程序与其他媒介交互产生的乱码。
下面对于这两种情况产生的乱码,分别说明解决方法:
第一种情况:(Java或JSP自身产生的乱码)
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"%>基本上就能解决这类乱码问题。这种情况比较简单。呵呵。如果有同事碰到特别的情况不能解决,不妨一起来讨论一下呀。
对于第二类的这种乱码,可能的情况比较多,我们也分别来看:
1、 页面参数传递是出现的乱码
这是因为Jsp获取页面参数时一般采用系统默认的编码方式,如果页面参数的编码类型和系统默认的编码类型不一致,很可能就会出现乱码。解决这类乱码问题的基本方法是在页
面获取参数之前,强制指定request获取参数的编码方式:request.setCharacterEncoding("GBK")或request.setCharacterEncoding("gb2312")。
如果在JSP将变量输出到页面时出现了乱码,可以通过设置
response.setContentType("text/html;charset=GBK")或response.setContentType
("text/html;charset=gb2312")解决。
在 JBoss+Jetty 中开发 JSP 时,当把页面编码设置为 gb2312 时,即
<%@ page contentType="text/html;charset=gb2312">
取参数前需要先设置一下 request 对象的编码, request.setCharacterEncoding("gb2312");
否则取出来的中文会是乱码,必须要手工转换,即:
new String(request.getParameter("click").getBytes("iso8859-1"),"gb2312"); 这样做就麻烦了。需要注意的是设置 request 对象的编码必须要在取所有的参数之前,否则就无效了。
Tomcat 支持 GBK 没有问题,不过 Jetty 缺省只能支持 GB2312。使用:
<%@ page contentType="text/html;CHARSET=utf-8" %> 是没有效果的。 有这个问题是因为在 Jetty 中将 GB2312 作为中国的缺省字符集。解决的方法是修改 Jetty 的代码,将 GB2312 改为 GBK(只有一个 Java 文件)。重新编译就可以支持 GBK 了。jetty4.21 版gbk的问题好象已经解决了,不过request仍然要编码
其实对于这种情况更简洁的处理办法就是使用servlet规范中的过滤器指定编码,在这里也提供一个简单
的配置参考。
Web.xml:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.test.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,可以在驱动的url参数中指定, 如mysql驱动:jdbc:mysql://localhost/WEBCLDB?useUnicode=true&characterEncoding=GBK。
不过像现在在实际的项目中,数据库的编码格式可能我们是没有办法修改的,这样的话,也就只能是针对现在的数据库的编码格式对提取出来的数据进行转码。如果是在中文的环境下,基本上是不需要转码的,因为是从GBK-?GBK,(以报表为例),如果数据库的编码是ISO-8859-1的话,就需要转为GBK来处理,否则就会出现乱码的问题了,在最近的项目中还遇到了一种情况,那就是在SQL语句中存在中文,这种情况在目前的报表工具中还是比较多的,中文环境下不需要坐任何的处理,在ISO-8859-1的环境下,需要将GBK再转换为ISO-8859-1来处理,否则SQL中的中文在页面上看到的就是?,
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、其他
上面说的这几种情况可以解决大部分的乱码问题,如果在其他地方出现乱码,可能就需要手工的来进行转码了,解决这类问题的关键就在于字节和字符的转换过程,你必须清楚地知道原来的字节或转换后的字节的编码方式,也就是说转换时采用的编码必须与这个编码方式一致。
在实际的项目碰到了一种情况,就是用servlet直接输出页面的情况,(这种通过servlet输出页面的方式我个人是不推荐使用了,不过以前的项目遗留下来的,那也就没有办法了,呵呵!)这里就说到PrintWriter和ServletOutputStream的区别,个人的建议,如果是涉及到字符的转换强烈推荐使用PrintWriter,虽然会占用一些系统的开销,但是可以很好的帮助解决乱码的问题,更详细的可以参考我的另一篇文章《PrintWriter 与 。
总结:在处理java的编码问题时,要分清楚三个概念:Java采用的编码:unicode,JVM平台默认字符集和外部资源的编码。这样我们在面对乱码的问题时,解决起来就游刃有余了。
这个JVM平台默认字符集在虚拟机启动时决定,通常根据语言环境和底层操作系统的 charset 来确定。可以通过以下方式得到JVM的默认字符集:Charset.defaultCharset();
花了半天的时间总结了一番,自己再回头一想,解决乱码问题的思路就更清晰了,也希望此文能够切实的对其他同事在实际的工作中有所帮助,中间又说的不对的地方也请指正,共同进步!
热切希望此文能够被加为精华!
第一章 Java的基本语法
本文档由http://hitaow.sinaapp.com整理发布。
1.1:Java的注释:
1.// 单行注释
2./* */ 多行注释
3./** */ 是javadoc注释,在生成java文档时使用,例如使用它生成API文档,这种注释与 javadoc.exe(JDK的一部分)一并使用。
javadoc.exe Abc.java 如果想把Abc.java文件做成Java文档,可以使用上述命令。此时,javadoc
将会翻译/** */部分。
1.2:标识符:指用户自己定义的类别、变量名、方法名等。
命名标识符应该遵从以下几点原则:
1.区分大小写,长度不限。
2.英文、数字、下划线、美元符号均可使用,但不能以数字开头。 3.不能使用Java关键字。 正:
Abcde、abc12、_Hi、$abc、abc123abc
误:
3abc、#abc、this、super(this、super是Java关键字)
Java关键字
(1)基本数据类型 boolean、byte、char、short、int、long、float、double (2)访问控制 private、protected、public
(3)与类有关的关键字 class、abstract、interface、extends、implements (4)与对象有关的关键字 new、instanceof、this、super、null
(5)与方法有关的关键字 void、return
(6)控制语句 if、else、switch、case、default、for、do、while、break、continue (7)逻辑值 true、false
(8)异常处理 try、catch、finally、throw、throws (9)其他 transient、volatile、package、import、synchronized、native、final、static strictfp (10)停用的关键字 goto、const
1.3:变量与常量
小技巧:变量和方法均已小写字母开头。类名以大写字母开头。
1.4:数据类型
1:基本数据类型
A.逻辑型(Logical,也称布尔型) ----boolean(1 byte)
B.字符型 ----char(2 byte)
C.整型(Integral) ----byte(1 byte) short(2 byte) int(4 byte) long(8 byte) D.实数型(Floating,也称浮点数) ----float(4 byte ) double(8 byte) 2.对象数据类型(Object Type)
注意::对于整型数据,把超过其表示范围为的大整数赋给了变量时程序会出现错误。在超过int型表达范围的整数后,一定要加上字母L(或小写的l)。整型常数有int型与long型之分,long型常数后,一定要加上字母L或小写的L.。如: Int型常数:1,123,-12345,012,0x12 Long型常数:1L,2L,300L,0x12L
对于实数型如果想用float型小数,则要在小数后面添加上字母f或F。如:float a=1.23f
1.5. 类型转换
(1)..自动类型转换 系统会自动地将两个字节型数据相加的结果转换成整型,这就是 Java中所谓的自动类型转换。如下: x1 byte b1=1; x2 byte b2=2;
x3 byte b3=b1+b2;
事实上当编译时会出现错误,就是因为Java中这种自动类型转换机制。x3应改为
int b3=b1+b2; 。
下表列出了两个变量做某种运算后所得结果值的数据类型------
(2)..强制类型转换 格式为:(int)x [与C++不同C++有两种形式:(int)x和int(x)]。
1.6.运算符
运算符种类
1.6.2 位非运算符(~ ) 运算规则:逢0变1,逢1变0。
一个例题的疑问:byte a=7; byte b= ~a;
System.out.println(b); //会输出-8? 很遗憾上面的代码会报错,原因在于我们把~a这个整型数赋给了一个字节型变量。改正为 byte b=( byte )~a;怎么回事呢?
1.6.3 位移(shift)运算符(<<,>>,>>>)
“<<”将比特位左移一位,右端空位全部填0。 规律:每左移一位其值就增加1倍。
“>>”将比特位右移一位,被移动的若为正数,最左端填0;若为负数,其最左端填1。
规律:每右移1位,其值就减半。
“>>>”表示右移1位,并且无论被移的是正数还是负数,其最左端均填0。所以,用“>>>”运算符操作负数后,将得到正整数。
注意:这些运算符操作的数据是原始数据的副本,所以,操作后的原始值不变。 1.6.4 &&与||
小常识:A&&B:若A为false,则整个表达式即位假,与B的真假无关,所以运算时B并不被运算(即保持着原来的值)。 A ||B:一样。 运算时一定要注意。 所以&&与||又被称为短路运算符。<要补充例子> 1.6.5 位运算符:位与(&)、位或(|)、位移或(^)
A&B:比较两个操作数的比特位,若都为1,则结果为1,否则为0。 如果a=3,b=10,则a&&b是2。 a —>1110 b —>1010 a&&b—>0010
A|B:对应比特位有一个是1,则结果是1,否则为0。 A^B:对应比特位如果不相同,则结果1,否则是0。
1.6.6 三目运算符 (?:) 格式为:条件式?值1:值2 1.6.7 赋值运算符
其中几个特殊的符号,如下:
“a|=10”等价于a=a|10,把a|10的值赋给变量a,a的值为9。
1.6.8 对象运算符 其结果值是boolean型。
如:A instanceof B:如果A是B的对象,则返回true,否则,返回false。System.out.println(“abc”instanceof String);的结果是true.因为abc是String类的对象。
第二章 程序流程控制语句
控制语句 控制语句
(1)条件语句( if、switch) (2)循环语句(for、while、do~while)
功能
针对某条件进行某种处理 重复执行某段代码
(3)异常处理语句( try~catch~finally) 处理程序发生的异常 注:【1】条件语句和循环语句,这些和C++中的用法差不多。
【2】break语句在switch中,用于终止一种情形;在循环语句中,用于强制退出循
环。
【3】case:n中n的值可以为整数,但绝对不能是实数或字符串,如:case:5.4或case:”abc”是错误的。
【4】continue语句用于使程序流转到循环语句的“}”处,接着执行循环当条件不成立时才退出。
小常识:System.out.println(A):输出A后,将光标移至下一行。而System.out.print(A):输出A 后,将光标停留在本行,不会移动到下一行。 例题:
For11.java
public class For11{ public static void main(String[] args){ for(int a=1;a<=3:a++){
for(int b=1;b<=2;b++){ if(a<=2)continue;
System.out.println(a+” “+b);
} 输出结果为: 你好 1
System.out.println(“你好”+a); 你好 2 } 3 1 } 3 2 } 你好 3
For12.java
public class For12{
public static void main(String[] args){ outer:for(int a=1;a<=3;a++){ for(int b=1;b<=2;b++){ if(a<2)continue outer;
System.out.println(a+” “+b); }
System.out.println(“你好”+a); 输出结果为:3 1
} 3 2
} 你好 3
“outer:”字样的标记,我们把这种标记称为标签(lable),也可以把它理解成一种标示或标识。标签名可以使用任何合法的标识符。
For13.java //输出九九乘法表
public class For13 {
public static void main(String[] args){ for(int a=1;a<=9;a++){ } }
}
for(int b=1;b<=a;b++){
System.out.print(a+"*"+b+"="+a*b+" "); }
System.out.println();
For15.java //输出图形
public class For15 {
public static void main(String[] args){
for(int a=5;a>=1;a--){ for(int b=1;b<=a;b++){ System.out.print("*");
}
System.out.println();
}
} }
问题:1.根据下面的提示,编制程序输出以下的结果。? 1 23
345 4567 56789
2.编写程序,用于判断某个整数n(=29)是素数还是和数。? n是素数。
第三章 类与对象
第十八章 网络程序设计 18.1 网络程序设计基础
网络程序设计是指编写与其他计算机进行通信的程序。
18.1.1 TCP与UDP
TCP(Transmission Control Protocol,传输控制协议)协议负责数据或文件的分组与重组,而IP协议则负责发送与接收数据包。数据或文件在网络上传输的时候会被分成许多块,成为包(packet)。
UDP(User Datagram Protocol,数据报协议)协议他与TCP协议的区别在于它
并不对连接的状态与数据损失作检查。即,UDP协议是一种无连接的、不可靠的
通信协议。TCP中所谓的包在UDP中称为数据报(datagram)。TCP与UDP都支持数据的双向传递(full duplex,全双工)。
18.1.2 端口与套接字
端口并不是真实的物理存在,而是一个假想的连接装置。
套接字(socket)是一个软件实现,它是一个假想的连接装置用于将应用程
序与端口连接起来。 Java将套接字抽象化为类。因此,程序设计者只需创建Socket类对象,即
可使用套接字。
18.2 TCP程序设计基础
Java中的TCP网络程序设计是指利用Socket类,编写通用程序。
Java中文乱码的解决方案jspServlet的形式在jsp页面向后台发送的请求里包含中文时后台采用Stringnamereque…
Java中文乱码转码问题总结20xx0505170408分类java字号订阅在JSPServlet中主要有以下几个地方可以设置编码…
自从接触Java和JSP以来就不断与Java的中文乱码问题打交道现在终于得到了彻底的解决现将我们的解决心得与大家共享一Java中文…
个人总结java中处理乱码问题个人总结java乱码的问题的可谓是老生常谈了自从接触java以来就不断地与中文乱码的问题打交道最近的…
JavaJSP中文乱码问题解决心得自从接触Java和JSP以来就不断与Java的中文乱码问题打交道现在终于得到了彻底的解决现将我们…
Java中文乱码的解决方案jspServlet的形式在jsp页面向后台发送的请求里包含中文时后台采用Stringnamereque…
Java中文乱码转码问题总结20xx0505170408分类java字号订阅在JSPServlet中主要有以下几个地方可以设置编码…
自从接触Java和JSP以来就不断与Java的中文乱码问题打交道现在终于得到了彻底的解决现将我们的解决心得与大家共享一Java中文…
JavaJSP中文乱码问题解决心得自从接触Java和JSP以来就不断与Java的中文乱码问题打交道现在终于得到了彻底的解决现将我们…
Javaweb编程中经常遇到汉字的问题现在总结一下工程的编码模式是utf8我遇到的最多的问题就是通过由前台向后台传值解决方法就行后…