/Users/chenjp/tmp/yey/b.txt
文件内容
杀菌~ABC的
读取文件的代码
public class Demo {
public static final String FILE_OUTPUT_PATH = "/Users/chenjp/tmp/yey/b.txt";
public static void main(String[] args) throws IOException {
FileInputStream fos = new FileInputStream(FILE_OUTPUT_PATH);
int b ;
while((b=fos.read())!=-1){
System.out.print((char) b);
}
fos.close();
System.out.println();
}
}
读取文件的输出结果
Connected to the target VM, address: '127.0.0.1:62594', transport: 'socket'
æ€èŒï½žABCçš„
Disconnected from the target VM, address: '127.0.0.1:62594', transport: 'socket'
Process finished with exit code 0
在计算机中,任意数据都是以二进制的形式来存储的,单位bit(比特),8bit是1 byte(字节),字节是计算机最小的存储单元。存储英文只需要1个字节就行,中文需要2字节。
ASCII 英文
GBK 英文&中文
Unicode 英文&中文
英文
a
存储时对应ASCII
码是97,对应二进制110 0001
,存储时是以1字节存储,需要8位的二进制,所以要在二进制码前面补0,补齐8位 ,即0110 0001
。读取时,是读取
0110 0001
然后解码得到十进制97,查询ASCII码得到读取的英文a
国家在1980年发布了国家标准的信息交换用汉字编码字符集
GB 2312-80
,收录了7445个图形字符,其中包括6763个简体汉字。台湾地区繁体字在
BIG5
字符集中收录,共收录了13053个中文字,1984年实施。
2000年3月17日发布了
GBK
字符集,收录了21003个汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。在windows系统中默认使用的就是GBK,系统显示为
ANSI
,所以ANSI就是GBK。
GBK也是完全兼容 ASCII 的。存储英文时与 ASCII 一样。二进制前面补 0 。
存储一个汉字时使用两个字节进行存储
前面的第一个字节叫高位字节,后面的叫地位字节。
高位字节二进制一定以 1 开头,转成十进制之后是一个负数
这里高位一定要以1开头是为了区分中文和英文,在读取二进制的时候,读取到1开头的字节就知道后面两个字节表示一个汉字,如果读取到0就表示当前字节是表示英文的。
Unicode字符集,国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。
a --> 查询Unicode. --> 97 --> 编码
UTF(Unicode Transfer Format ) Unicode转换格式
采用UTF-16编码规则:用2~4个字节保存 a -> 0000 0000 0110 0001
采用UTF-32编码规则:固定用4个字节保存 a -> 0000 0000 0000 0000 0000 0000 0110 0001
采用UTF-8编码规则: 用1~4个字节保存
在UTF-8中,
ASCII中的所有字符都适用1个字节表示, 0xxx xxxx (ASCII码)
叙利亚等国家语言使用2字节表示, 110x xxxx 10xx xxxx
中文等国家语言使用3个字节表示, 1110 xxxx 10xx xxxx 10xx xxxx
也有用4个字节表示的语言。 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
存储汉字
汉
查询
Unicode编码集
得到27721
,对应0110 1100 0100 1001
再进行UTF-8编码 ,
1110 0110 1011 0001 1000 1001
这里的填补规则就是将
0110 1100 0100 1001
填补到1110 xxxx 10xx xxxx 10xx xxxx
中的x部分
比如说读取
1110 0100 1011 1101 1010 0000
时,这应该读取出来是一个可查询到汉字的编码,但是没有将这3个字节读取完,只读取了一个字节1110 0100
,这个二进制表示-28,但是-28在编码集中查询不到对应的符号,这时操作系统就会显示???
或者其他符号,这就造成了乱码。
比如说存储汉字时用
UFT-8
进行存储的,这时采用3个字节表示这个汉字,但是解码的时候使用了GBK
进行了解码,但是GBK中汉字是2个字节表示的,只会读取编码后的3个字节的前2个字节进行解码,这时候编码和解码的就会出现问题,导致乱码。
- 不要使用字节流读取文本文件
- 编码解码时使用同一个码表,同一个编码方式
字节流读取中文会乱码,但是为什么拷贝不会乱码呢?
这是因为所有的字节都拷贝过去了,并且源文件的写入方式和拷贝后的文件打开方式使用的是同一种编码方式,所以就不会乱码。
String类中的方法 | 说明 |
---|---|
public byte[] getBytes( ) | 使用默认方式进行编码 |
public byte[] getBytes( String charsetName ) | 使用指定方式进行编码 |
String类中的方法 | 说明 |
---|---|
String( byte[ ] bytes ) | 使用默认方式进行解码 |
String( byte[ ] bytes , String charsetName ) | 使用指定方式进行解码 |
public class BianMa {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "ai你哟";
byte[] bytes = str.getBytes();
System.out.println("编码结果:");
System.out.println("UTF-8编码 "+Arrays.toString(bytes));
byte[] bytes1 = str.getBytes("GBK");
System.out.println("GBK编码 "+Arrays.toString(bytes1));
System.out.println("解码结果: ");
String string = new String(bytes);
System.out.println("UTF-8解码原UTF-8 "+string);
String string1 = new String(bytes,"GBK");
System.out.println("GBK解码原UTF-8 "+string1);
String string2 = new String(bytes1);
System.out.println("UTF-8解码原GBK "+string2);
}
}