Java字符编码问题

时间:2022-06-16 15:42:02

常见编码

ASCII码,128个,一个字节的低7位表示

ISO-8859-1,256个,单字节

GB2312,中文编码字符集,双字节编码,A1~F7,682个符号,6763个汉字

GBK,汉字内码扩展规范,兼容GB2312,21003个汉字,双字节

UTF-16,定长,用两个字节表示Unicode的转化格式,、

UTF-8,变长,不同类型字符可以由1~6个字节组成,汉字3个字节。

java字符编码转换

一般涉及编码的地方都存在字符到字节或字节到字符的转换上。

I/O操作中的编码

InputStreamReader和OutputStreamWriter

InputStreamReader完成byte流解析为char流,按照编码解析。

OutputStreamWriter完成char流到byte流,按照编码处理。

InputStreamReader isr = new InputStreamReader(new FileInputStream("test1.txt"),"utf-8");//使用文件编码读
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("test2.txt"),"utf-8");//写入文件的编码,可以为其他编码,如gbk

 

内存操作中的编码

string.getBytes("charsetName")

这是java字符串处理的一个标准函数,其作用是将字符串所表示的字符按照charsetName编码,并以字节方式表示。

newString(byte[],"charsetName")

将字节数组按照charsetName编码进行组合识别,最后转换为unicode存储。

 

一个简单测试例子:

public class Main {
   
public static void main(String[] args) {
       
try {
            String test =
"一二三",str;
           
System.out.println(System.getProperty("file.encoding"));//UTF-8
            //
传输过程中用什么编码,接收时就用什么解码
           
//测试使用UTF8(三字节)和GBK(二字节)
           
System.out.println(test.getBytes("UTF8").length);
           
System.out.println(test.getBytes("GBK").length);
           
//解码默认,编码默认
           
str=new String(test.getBytes());
           
System.out.println(str+str.length());//正常
           
//解码默认,编码GBK
           
str=new String(test.getBytes(),"GBK");
           
System.out.println(str+str.length());//乱码
           
//解码GBK,编码默认
           
str=new String(test.getBytes("GBK"));
           
System.out.println(str+str.length());//乱码
           
//解码GBK,编码GBK
            //
虽然test本来默认是三字节编码的,但getBytes("GBK")
            //
把整个字节数组按双字节形式转换了一次。用GBK来解释这个新字节数组就对了
           
str=new String(test.getBytes("GBK"),"GBK");
           
System.out.println(str+str.length());//正常

           
//回不去?部分字符能转换
           
str=new String(test.getBytes(),"GBK");
           
str=new String(str.getBytes("GBK"),"UTF8");
           
System.out.println(str);

       
} catch (UnsupportedEncodingException ex) {
            Logger.getLogger(Main.
class.getName()).log(Level.SEVERE, null, ex);
       
}
    }
}

 

Charset类

Charset提供encode与decode分别对应char[]到byte[]和byte[]到char[]。

String str = "你好";
Charset charset = Charset.forName("UTF8");
charset.encode(str);
ByteBuffer byteBuffer = charset.encode(str);
CharBuffer charBuffer = charset.decode(byteBuffer);
System.out.println(charBuffer.toString());

 

JavaWeb中的编码

浏览器编码URL是将非ASCII字符按照某种编码格式编码成16进制数字后,将每个16进制表示的字节前加上“%”

对URL的URI部分进行解码的字符集是在connector的<Connector URIEncoding=”UTF-8”/>中定义的,没有定义则使用默认编码ISO-8859-1。

而对于QueryString的解析过程,GET和POST都作为parameters保持,对它们的解码是在request.getParameter方法第一次被调用时进行的。

request.setCharacterEncoding()

该函数用来设置http请求或者相应的编码。只对POST方法有效,对GET方法无效。setCharacterEncoding()之前,不能执行任何getParameter()。

对于GET方法,要将connector的<Connector URIEncoding=”UTF-8” useBodyEncodingForURI=”true”/>。

URLEncode.encode()

对的URL编码函数

String mytext = java.net.URLEncoder.encode("中国", "utf-8");
String mytext2 = java.net.URLDecoder.decode(mytext, "utf-8");
//
分别为%E4%B8%AD%E5%9B%BD中国
String zhongguo = new String(request.getParameter("zhongguo").getBytes("iso8859_1"));
zhongguo = java.net.URLDecoder.decode(zhongguo, "utf-8");