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();
}
}
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();
}
}
相关文章推荐
- java 字符编码 解码 转码 识别编码
- Java中的字符编码与解码(转)
- Java 字符编码与解码
- Java IO学习【19】Java中字符编码解码小知识
- Java中的字符编码与解码 utf8 utf16 gbk
- 深入分析字符编码之三-Java 中如何编解码
- Java 字符编码与解码
- java中关于字符编码解码的思考
- Java NIO框架Netty教程 (十) Object对象编/解码
- 字符编码/解码及相关概念
- 黑马程序员——JAVA 编解码表与GUI
- JAVA实现QCODE解码技术
- java读取网页 正确处理字符编码
- [置顶] 字符编码和Java中的乱码问题
- Java实现BASE64Decoder编写加密和解码
- Java利用QRCode.jar包实现二维码编码与解码
- Java利用QRCode.jar包实现二维码编码与解码
- JAVA初窥:字符编码
- JAVA中文字符编码问题详解 控制台输出,字符编码格式转换
- 在Java中正确解码用Javascript:escape()编码的中文字符