1.字符编码
编码:字符(能看懂的)-->字节(看不懂的)
解码:字节(看不懂的)-->字符(能看懂的)
乱码:按照A规则存储,同样按照A规则解析,那么会显示正确的文本符号;
反之,按照A规则存储,再按B规则解析,会导致乱码现象。
字符编码(Character Encoding):就是一套自然语言的字符与二进制数之间的对应规则
编码表:生活中文字和计算机中二进制的对应规则
2.字符集就是编码表,是系统所有字符的集合,包括各个国家文字、标点符号、图形符号、数字
等
编码引发的乱码问题:
package iotest.bufferedIOtest; /*FileReader在IDEA中默认的编码格式为UTF-8 * FileReader读取系统默认编码(GBK),会出现乱码 * */ import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; public class ErrorCodeTest { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("C:\\test\\系统默认GBK编码文本1.txt"); int len =0; while ((len = fr.read()) != -1){ System.out.print((char) len); } fr.close(); } }
运行结果为:
源文件内容为:
乱码问题解决方法:用转换流
转换流的强大之处为:可以指定编码表(OutputStreamWriter、InputStreamReader可指定特定的编码表)
GBK编码中,一个中文占两个字节
UTF-8编码中,一个中文占三个字节
OutputStreamWriter 类
java.io.OutputStreamWriter extends writer
OutputStreamWriter:是字符流向字节的桥梁,可使用指定的charset将要写入流中的字符编码成字节(编码:把能看懂的变成看不懂的)
写在硬盘上的都是字节,当打开文件时,会调用系统的编码表来解码
构造方法:
public OutputStreamWriter(OutputStream out, String charsetName)
public OutputStreamWriter(OutputStream out)--默认编码表为UTF-8
参数:
OutputStream out:字节输出流,可以把转换之后的字节写入到指定文件
String charsetName:指定编码表名称,不区分大小写,utf-8/UTF-8,gbk/GBK都行
使用步骤:
1.创建OutputStreamWriter对象,构造方法中传递指定的字节输出流和指定的编码表名称
2.使用OutputStreamWriter的write方法,将字符转化为字节,存储在缓冲区中(编码)
3.使用OutputStreamWriter的flush方法,将内存中的字节写到硬盘文件中(使用字节流写的过程)
4.释放资源
package iotest.changeeachother; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; public class TestOutputStreamWriter01 { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("C:\\test\\h.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");//编码表用的是GBK,也可以写UTF-8 osw.write("你好啊",0,2); osw.write("就你那女女女"); osw.close(); } }
InputStreamReader类
java.io.InputStreamReader extends Reader
InputStreamReader:是字节流向字符的桥梁,可使用指定的charset将要写入流中的字节编码成字符
从硬盘上读取的都是字节,此时编码表以确定,需要与源文件编码表相一致
构造方法:
public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in, String charsetName)
参数:
InputStream in:字节输入流,可以将硬盘上的文件以字节的形式读取到内存中
String charsetName:指定编码表名称,不区分大小写,utf-8/UTF-8,gbk/GBK都行
使用步骤:
1.创建InputStreamReader对象,构造方法中传递指定的字节输入流和指定的编码表名称
2.使用InputStreamReader的read方法,将字节转化为字符,放在内存中使用(解码)
3.释放资源
注意事项
构造方法中的指定的编码表名称要与源文件的编码表名称相同,否则会出现乱码
(系统已经按系统的编码表进行编译成字节,此时若用不一样的编码表,会出现乱码)
package iotest.changeeachother; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; public class TestInputStreamReader01 { public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\test\\系统默认GBK编码文本1.txt"),"utf-8");//源文件使用的编码表为GBK,而此时设置为utf-8,会出现乱码 int len = 0; //若设置为GBK,不会出现乱码 while ((len = isr.read()) != -1){ System.out.print((char) len); } isr.close(); } }
运行结果
练习:转换文件编码:将GBK编码文件转化为UTF-8编码的文件
package iotest.changeeachother; import java.io.*; //转换文件编码:将GBK编码文件转化为UTF-8编码的文件 public class GBKtoUtf { public static void main(String[] args) throws IOException { InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\test\\GBK文件.txt"),"GBK");//这里必须是GBK OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("C:\\test\\UTF-8文件.txt"),"UTF-8"); int len = 0; while ((len = inputStreamReader.read()) != -1){ outputStreamWriter.write(len); } outputStreamWriter.close(); inputStreamReader.close(); } }