您的位置:首页 > 编程语言 > Java开发

Java中的字符编码与解码

2010-03-08 17:04 197 查看
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();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: