java中的字节、字符、编码以及中文乱码问题

来源:互联网 发布:飞船设计软件 编辑:程序博客网 时间:2024/04/29 18:51

1、中英文编码

1. 英文字母:A
2. 字节数:1;编码:GB2312
3. 字节数:1;编码:GBK
4. 字节数:1;编码:GB18030
5. 字节数:1;编码:ISO-8859-1
6. 字节数:1;编码:UTF-8
7. 字节数:4;编码:UTF-16
8. 字节数:2;编码:UTF-16BE
9. 字节数:2;编码:UTF-16LE
10. 中文汉字:人
11. 字节数:2;编码:GB2312
12. 字节数:2;编码:GBK
13. 字节数:2;编码:GB18030
14. 字节数:1;编码:ISO-8859-1
15. 字节数:3;编码:UTF-8
16. 字节数:4;编码:UTF-16
17. 字节数:2;编码:UTF-16BE
18. 字节数:2;编码:UTF-16LE

输入途径:
 1、通过页面表单打包成请求 (request)发往服务器的;
 2、通过数据库读入;
 3、JSP在第一次运行时总是被编译成Servlet,JSP中常常包含中文字符,那么编译使用javac时,Java将根据默认的操作系统编码作为初始编码。除非特别指定,如在                    eclipse中可以指定默 认的字符集。
输出途径:
 1、JSP页面的输出。
 由于JSP页面已经被编译成Servlet,那么在输出时,也将根据操作系统的默认编码来选择输出编码,除非指定输出编码方式;
 2、数据库,将字符串输出到数据库。
解决中文乱码的根本办法是明确指定整个应用系统统一字符集。
  1、指定统一字符集ISO8859_1 、GBK(只能在相应的操作系统上运行):
a. 开发和编译代码时指定字符集为ISO8859_1(GBK)。
b. 运行操作系统的默认编码必须是ISO8859_1(中文Windows默认是GBK),如Linux。
c. 在JSP头部声明:。
  2、UTF-8
 a. 开发和编译代码时指定字符集为UTF-8。Eclipse都可以在项目属性中设置。
 b. 使用过滤器,如果所有请求都经过一个Servlet控制分配器,那么使用Servlet的filter执行语句,将所有来自浏览器的请求(request)转换为UTF-8,因为浏览器                                 发过来的请求包根据浏览器所在的操作系统编码,可能是各种形式编码。
 关键一句request.setCharacterEncoding("UTF-8")。网上有此filter的源码,Jdon框架源码中com.jdon.util.SetCharacterEncodingFilter需要配置web.xml 激                                    活该Filter。
 c. 在JSP头部声明:在Jsp的html代码中,声明UTF-8:
 d. 设定数据库连接方式是UTF-8。例如连接MYSQL时配置URL如下:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8, 一般数据                                  库都可以通过管理设置设定UTF-8
 e. 其他和外界交互时能够设定编码时就设定UTF-8,例如读取文件,操作XML等


Java中文问题的由来:
    Java的内核和class文件是基于unicode的。
     1、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"%>基本上就能解决这类乱码问题
2、Java程序与其他媒介交互产生的乱码问题
      1) 从页面form提交数据到java程序 byte->char;从java程序到页面显示 char->byte
     页面参数的编码类型和系统默认的编码类型不一致
 request.setCharacterEncoding("gb2312")。如果在JSP将变量输出到页面时出现了乱码,可以通过设置
                  response.setContentType("text/html;charset=GBK")或response.setContentType("text/html;charset=gb2312")解决。
 或者:
  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程序 byte->char;从java程序到数据库 char->byte
                   大部分数据库都支持以unicode编码方式,所以解决Java与数据库之间的乱码问题比较明智的方式是直接使用unicode编码与数据库交互。很多数据库驱动自动支持unicode,如Microsoft的SQLServer驱动。其他大部分数据库驱动,可以在驱动的url参数中指定,如如mm的
                   mysql驱动:jdbc:mysql://localhost/WEBCLDB?useUnicode=true&characterEncoding=GBK。  
  3)从文件到java程序 byte->char;从java程序到文件 char->byte
  4)从流到java程序 byte->char;从java程序到流 char->byte
Java读写文件最常用的类是FileInputStream/FileOutputStream和FileReader/FileWriter。
其中FileInputStream和FileOutputStream是基于字节流的,常用于读写二进制文件。
读写字符文件建议使用基于字符的FileReader和FileWriter,省去了字节与字符之间的转换。
但这两个类的构造函数默认使用系统的编码方式,如果文件内容与系统编码方式不一致,可能会出现乱码。
在这种情况下,建议使用FileReader和FileWriter的父类:
InputStreamReader/OutputStreamWriter,它们也是基于字符的,但在构造函数中可以指定编码类型:
InputStreamReader(InputStream in, Charset cs) 和OutputStreamWriter(OutputStream out, Charset cs)。
  
     字符集与字符编码:
   Unicode编码系统为表达任意语言的任意字符而设计。它使用4字节的数字来表达每个字母、符号,或者表意文字(ideograph)。每个数字代表唯一的至少在某种语言中使用的符号。(并不是所有的数字都用上了,但是总数已经超过了65535,所以2个字节的数字是不够用的。)被几种语言共用的字符通常使用相同的数字来编码,除非存在一个在理的语源学(etymological)理由使不这样做。不考虑这种情况的话,每个字符对应一个数字,每个数字对应一个字符。即不存在二义性。不再需要记录"模式"了。U+0041总是代表'A',即使这种语言没有'A'这个字符。
Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三种字符编码方案




0 0
原创粉丝点击