- import java .io.BufferedReader;
- import java .io.FileInputStream;
- import java .io.FileNotFoundException;
- import java .io.FileOutputStream;
- import java .io.IOException;
- import java .io.InputStreamReader;
- import java .io.OutputStream;
- import java .io.OutputStreamWriter;
- import java .io.UnsupportedEncodingException;
- import junit.framework.TestCase;
- /**
- * 编码与解码测试
- * @author jzj
- */
- public class TestEncodeDecode extends TestCase {
- private char chineseChar = '中' ;
- private char englishChar = 'a' ;
- /**
- * Java 程序中的字符都是占用二个字节,因为 char 类型好比双字节的无符号整数
- */
- public void testCharToUnicode() {
- //十进制Uncode编码
- System.out.println((int ) chineseChar);//20013
- System.out.println((int ) englishChar);//97
- //十六进制Uncode编码
- System.out
- .println(Integer.toHexString((int ) chineseChar).toUpperCase());//4E2D
- System.out
- .println(Integer.toHexString((int ) englishChar).toUpperCase());//61
- //二进制Uncode编码
- System.out.println(Integer.toBinaryString((int ) chineseChar));//100111000101101
- System.out.println(Integer.toBinaryString((int ) englishChar));//1100001
- }
- /**
- * 不管是中文还是英文都还是其他字符,每个字符都是占用两个字节,英文字符的
- * UTF-16编码与Unicode编码是一样的,只不过UTF-16在编码时会在码流前加上"FE FF"两个字节的内容,
- * 表示字符是以UTF-16格式存储的,在读取时程序就会知道是UTF-16编码的字符
- */
- public void testCharToUTF16() {
- try {
- //--中文字符转UTF-16
- byte [] encodeArr = String.valueOf(chineseChar).getBytes("UTF-16" );
- //十进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //-2 -1 78 45
- System.out.print(encodeArr[i] + " " );
- }
- System.out.println();
- //十六进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //FE FF 4E 2D
- System.out.print(byteToHex(encodeArr[i]) + " " );
- }
- System.out.println();
- //所占字节数
- System.out.println(encodeArr.length - 2 );//2
- //--英文字符转UTF-16
- encodeArr = String.valueOf(englishChar).getBytes("UTF-16" );
- //十进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //-2 -1 0 97
- System.out.print(encodeArr[i] + " " );
- }
- System.out.println();
- //十六进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //FE FF 00 61
- System.out.print(byteToHex(encodeArr[i]) + " " );
- }
- System.out.println();
- //所占字节数
- System.out.println(encodeArr.length - 2 );//2
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
- /**
- * 以UTF-16写入文件时,也会把文件编码标志FE FF写入文件开头,但写入时不能编一码写一次文件,
- * 因为这样每次以UTF-16编码时,都会生成编码标志,且写文件时也写入了,这样只需第一次写文件
- * 时需要的标志却存入了多次,所以当以UTF-16存储字符时,最好一次性编码完成后再写入,或当字
- * 符太多时,我们用OutputStreamWriter进行包装后可以方便地进行多次写入,而不会多次写入文
- * 件编码标志,或者我们就用字节流来存,自已负责编码,但从第二次编码后写文件开始,手动去掉文
- * 件编码标志后再存入也是可以的,只不过没有像直接以字符流多次写入那样方便了。
- */
- public void testUTF16File() {
- try {
- //--字节流多次写错误
- byte [] encodeArr = String.valueOf(chineseChar).getBytes("UTF-16" );
- OutputStream o = new FileOutputStream("e:/utf16.txt" );
- o.write(encodeArr);
- encodeArr = String.valueOf(englishChar).getBytes("UTF-16" );
- o.write(encodeArr);
- o.close();
- //--读
- BufferedReader br = new BufferedReader(new InputStreamReader(
- new FileInputStream("e:/utf16.txt" ), "UTF-16" ));
- //因为存储方法错误,所以导致读取时出现乱码,其实问号就是文件编码标志
- System.out.println(br.readLine());//中?a
- br.close();
- //--正确字节流多次写
- encodeArr = String.valueOf(chineseChar).getBytes("UTF-16" );
- o = new FileOutputStream("e:/utf16.txt" );
- o.write(encodeArr);
- encodeArr = String.valueOf(englishChar).getBytes("UTF-16" );
- //从第二次开始写入时,不要把文件编码多次写入文件,这样存储会正确
- o.write(encodeArr, 2 , encodeArr.length - 2 );//中a
- o.close();
- //--读
- br = new BufferedReader(new InputStreamReader(new FileInputStream(
- "e:/utf16.txt" ), "UTF-16" ));
- System.out.println(br.readLine());//中a
- br.close();
- //--正确的字符流写
- OutputStreamWriter ow = new OutputStreamWriter(
- new FileOutputStream("e:/utf16.txt" ), "UTF-16" );
- ow.write(chineseChar);
- ow.write(englishChar);
- ow.close();
- //--读
- br = new BufferedReader(new InputStreamReader(new FileInputStream(
- "e:/utf16.txt" ), "UTF-16" ));
- System.out.println(br.readLine());//中a
- br.close();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * 英文字符以UTF-8编码时只占一个字节或二字节(编码大于128小于256的英文字符),编码小于等于128的
- * 字符UTF-8字符与Unicode编码兼容,中文字符以UTF-8编码时,占三个字节。
- * 英文、中文使用的UTF-8编码规则模板分别是0xxxxxxx、1110xxxx 10xxxxxx 10xxxxxx
- * 如"中"字的Unicode编码是4E2D。4E2D在0800-FFFF之间,所以要用上面的三字节规则模板,
- * 将4E2D写成二进制是:0100 1110 0010 1101,将这个比特流按三字节模板的分段方法分为
- * 0100 111000 101101,依次代替模板中的x,得到:1110-0100 10-111000 10-101101,
- * 即 E4 B8 AD,这就是"中"字的UTF8的编码。
- */
- public void testCharToUTF8() {
- try {
- //--中文字符转UTF-8
- byte [] encodeArr = String.valueOf(chineseChar).getBytes("UTF-8" );
- //十进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //-28 -72 -83
- System.out.print(encodeArr[i] + " " );
- }
- System.out.println();
- //十六进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //E4 B8 AD
- System.out.print(byteToHex(encodeArr[i]) + " " );
- }
- System.out.println();
- //所占字节数
- System.out.println(encodeArr.length);//3
- //--英文字符转UTF-8
- encodeArr = String.valueOf(englishChar).getBytes("UTF-8" );
- //十进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //97
- System.out.print(encodeArr[i] + " " );
- }
- System.out.println();
- //十六进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //61
- System.out.print(byteToHex(encodeArr[i]) + " " );
- }
- System.out.println();
- //所占字节数
- System.out.println(encodeArr.length);//1
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
- /**
- * 用Java 程序入文件中以UTF-8编码方式存入字符时,是不会在文件头加上编码标志的。
- * 但如果在windows中用记事本创建一个文件,并以UTF-8保存时,会在文件开开头写
- * 入文件编码标志 EF BB BF 三个字节长度的编码标志,这时如果使用字节流方式读取
- * 有编码标示的UTF-8文件时,会有问题,此时只能以字节流读出后去掉前三个字节内容
- */
- public void testUTF8File() {
- try {
- //--字节流写
- byte [] encodeArr = String.valueOf(chineseChar).getBytes("UTF-8" );
- OutputStream o = new FileOutputStream("e:/utf8.txt" );
- o.write(encodeArr);
- encodeArr = String.valueOf(englishChar).getBytes("UTF-8" );
- o.write(encodeArr);
- o.close();
- //--读
- BufferedReader br = new BufferedReader(new InputStreamReader(
- new FileInputStream("e:/utf8.txt" ), "UTF-8" ));
- System.out.println(br.readLine());//中a
- br.close();
- //--以字符流的方式读取windows记事本创建的有文件编码标志的UTF-8文件时错误
- br = new BufferedReader(new InputStreamReader(new FileInputStream(
- "e:/utf-8-2.txt" ), "UTF-8" ));
- System.out.println(br.readLine());//?中a
- br.close();
- //--以字节流读取有编码标志的UTF-8文件
- FileInputStream fi = new FileInputStream("e:/utf-8-2.txt" );
- byte [] b = new byte [1024 ];
- int readCount = fi.read(b);
- //手动丢弃前三个字节的内容
- System.out.println(new String(b, 3 , readCount - 3 , "UTF-8" ));//中a
- fi.close();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * 英文字符以GBK编码时只占一个字节或二字节(编码大于128小于256的英文字符),编码小于等于128的
- * 字符GBK字符与Unicode编码兼容,中文字符以GBK编码时,占
- * 两个字节。
- * GBK对中文编码时,每个字节的最高位都是一
- */
- public void testCharToGBK() {
- try {
- //--中文字符转GBK
- byte [] encodeArr = String.valueOf(chineseChar).getBytes("GBK" );
- //十进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //-42 -48
- System.out.print(encodeArr[i] + " " );
- }
- System.out.println();
- //十六进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //D6 D0
- System.out.print(byteToHex(encodeArr[i]) + " " );
- }
- System.out.println();
- //所占字节数
- System.out.println(encodeArr.length);//2
- //--英文字符转GBK
- encodeArr = String.valueOf(englishChar).getBytes("GBK" );
- //十进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //97
- System.out.print(encodeArr[i] + " " );
- }
- System.out.println();
- //十六进制编码输出
- for (int i = 0 ; i < encodeArr.length; i++) {
- //61
- System.out.print(byteToHex(encodeArr[i]) + " " );
- }
- System.out.println();
- //所占字节数
- System.out.println(encodeArr.length);//1
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
- public void testCharFromUTF16() {
- try {
- byte [] encodeArr = String.valueOf(chineseChar).getBytes("UTF-16" );
- System.out.println(new String(encodeArr, "UTF-16" ));//中
- encodeArr = new byte [] { -0x2 , -0x1 , 0x4E , 0x2D };
- System.out.println(new String(encodeArr, "UTF-16" ));//中
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
- public static String byteToHex(byte b) {
- return Integer.toHexString((b & 0x000000FF ) | 0xFFFFFF00 ).substring(6 )
- .toUpperCase();
- }
- }