Java字符转码

1.关于文件转码

这里我对字符串进行了二进制解码和编码。

首先你要知道以下几点。

1.生活中的文字转成二进制格式的序列或其他格式的序列,叫做编码过程。而对二进制序列或其他格式序列解析成生活中的文字,叫做解码过程。

2.Java的string内部是用Unicode编码的字节数组存储字符串的,如果你Java源文件编码方式是GBK,那么JVM会以GBK读取源文件中“”双引号的字符串,将读取的GBK编码字节解析成字符,然后再对字符以Unicode编码成字节数组,并存储于内部。

3.无论你源文件以那种方式编写字符串,JVM最终都会对“双引号”字符进行转码成Unicode格式并存用string对象内部。

4.string.getBytes()方法是根据你平台或源文件默认的编码方式进行encoding(编码),放回的是编码后的字节数组。string.getBytes(String charsetName)能指定编码方式,不用担心内部Unicode编码->charsetName编码,Java会帮你处理这个过程。

5.new String(byte[] b,String charsetName)这个构造函数将对指定的byte[] b指定编码解析。

下面我举几个例子:

String src ="你好朋友";          //string的内部编码方式是Unicode
		
byte[] U = src.getBytes(); //我的project的文件使用的是 UTF-8 encoding,所以这里返回 UTF-8编码的字节数组
byte[] G = src.getBytes("GBK");
System.out.println(src.length());
System.out.println(U.length);
System.out.println(G.length);
System.out.println(Charset.defaultCharset());    //打印编译器默认编码格式

String str1 = new String(src.getBytes("utf-8"),"utf-8");
String str2 = new String(src.getBytes("utf-8"),"gb18030");
String str3 = new String(src.getBytes("utf-8"),"GBK");
String str4 = new String(src.getBytes("utf-8"),"latin1");
System.out.println(String.format("%s\n%s\n%s\n%s\n", str1,str2,str3,str4));


String str5 = new String(src.getBytes("GBK"),"utf-8");
String str6 = new String(src.getBytes("GBK"),"gb18030");
String str7 = new String(src.getBytes("GBK"),"GBK");
String str8 = new String(src.getBytes("GBK"),"latin1");
System.out.println(String.format("%s\n%s\n%s\n%s\n", str5,str6,str7,str8));

运行结果如下:

4        //字符串长度
12		 //平台默认编码为UTF-8,中文一个字占3字节,所以是12
8		 //指定放回的GBK编码,一个中文2字节,所以是8
UTF-8	 //默认编码(编译器或源文件编码方式)
你好朋友   		  //编码和解析方式一样,能成功解析
浣犲ソ鏈嬪弸		//utf-8编码的字节数组,指定解析方式为gb18030,不能能成功解析
浣犲ソ鏈嬪弸		//同理
ä½ å¥½æœ‹å‹	//latin1压根不支持中文

�������		//同理
你好朋友		 //原因是GBK是gb18030的子集,GBK只包含汉字,gb18030包含小数民族的字
你好朋友		 //编码和解析方式一样,能成功解析
ÄãºÃÅóÓÑ		//latin1压根不支持中文

结果分析:

1.new String(src.getBytes(“GBK”),“utf-8”);压根不是进行转码,这个是编码和解码过程。编码和解析方式不同,根本无法正常显示,这里解码有误过程,也非真正的转码。网上一些教程有错误。src.getBytes(“GBK”)只有这句内部进行了转码(Unicode——>GBK,返回了对应的字节数组。

文件转码的正确方式:

第一步:以正确的方式打开并读取文件(我这里是UTF-8文件).

第二步:将字符串读取出来,并使用getBytes(“GBK”)获取对应的编码的二进制数据。

第三步:将编码后的二进制数据以二进制的方式写入到文件中。(无需解析,直接存进去就可以了)

第四步:关闭输入输出流。

String path = "D:\\SogouQ\\access_log.20060803.decode.filter";   
String path2 = "D:\\mytext.txt";

BufferedReader br=null;
BufferedOutputStream bo=null;
try {
    br = new BufferedReader(new InputStreamReader(new FileInputStream(path),"utf-8"));
    bo =new BufferedOutputStream(new FileOutputStream(path2));
    String line = null;
    while ((line = br.readLine())!=null) {
        line=line+"\n";
        bo.write(line.getBytes("GBK"));
    }
}catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}finally {
    try {
        br.close();
        bo.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

2.URL编码

URL 只能使用 ASCII来通过因特网进行发送。由于 URL 常常会包含 ASCII 集合之外的字符,URL 必须转换为有效的 ASCII 格式。URL 编码使用 “%” 其后跟随两位的十六进制数来替换非 ASCII 字符。又因为我们日常生活中往往会用好很多字符,而URL又只能用ASCII,所以这里需要URL编码。

下面举个例子:

String src ="你好朋友";
String text1 = URLEncoder.encode(src, "utf-8");    //将UTF-8字符变成ASCII字符
String text2 = URLEncoder.encode(src, "gb18030");
String text3 = URLEncoder.encode(src, "GBK");
String text4 = URLEncoder.encode(src, "latin1");
System.out.println(String.format("%s\n%s\n%s\n%s\n", text1,text2,text3,text4));

String text5 = URLDecoder.decode(text1, "utf-8");
String text6 = URLDecoder.decode(text2, "gb18030");
String text7 = URLDecoder.decode(text3, "GBK");
String text8 = URLDecoder.decode(text4, "latin1");
System.out.println(String.format("%s\n%s\n%s\n%s\n", text5,text6,text7,text8));

输出结果:

%E4%BD%A0%E5%A5%BD%E6%9C%8B%E5%8F%8B     //一个字节编码成3个符号(% + 2个16进制数)
%C4%E3%BA%C3%C5%F3%D3%D1
%C4%E3%BA%C3%C5%F3%D3%D1
%3F%3F%3F%3F            //Latin不支持中文,所以都是%3F

你好朋友
你好朋友
你好朋友
????    //Latin不支持中文