字符编码和字符集
字符编码
计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。
编码:字符 --> 字节
解码:字节 --> 字符
字符编码,是一套自然语言的字符与二进制数之间的对应规则。
字符集
字符集,也叫编码表,是一个系统支持的所有字符集合,包括国家文字、标点符号、图形符号、数字等。
计算机要准确的存储和识別各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。
编码引出的问题
在IDEA中,使用FileReader读取项目中的文本文件。由于IDEA的设置,都是默认的UTF-8编码,所以没有任何问题。但是,当读取系统中创建的文本文件时,由于系统的默认是GBK编码,就会出现乱码。
那么该如何解决呢?我们可以使用InputStreamReader类、OutputStreamWriter类,指定编码来进行读写操作,这时候就不会出现乱码的情况了。
OutputStreamWriter类
java.io.OutputStreamWriter是字符流通向字节流的桥梁:可使用指定的charset将要写入流中的字符编码成字节(编码)。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
OutputStreamWriter类是java.io.Writer的子类,所以可以使用父类方法:
public void write(intc)//写入单个字符。
public void write(charcbuf[])//写入字符数组。
abstract public void write(char cbuf[], int off, intlen)//写入字符数组的某一部分,off是数组的开始索引,len是写的字符个数。
public voidwrite(String str)//写入字符串。
public void write(String str, int off, intlen)//写入字符的某一部分。off是字符的开始素,len是写的字符个数。
abstract public voidflush()//刷新该流的缓冲。
abstract public voidclose()//关闭此流,但会先刷新它。
构造方法
OutputStreamWriter(OutputStream out)//创建使用默认编码的OutputStreamWriter对象
OutputStreamWriter(OutputStream out, String charsetName)//创建使用指定编码的OutputStreamWriter对象
参数:
OutputStreamWriter out:字节输出流
String charsetName:指定编码表的名称,不区分大小写。如utf-8/UTF-8。
使用步骤:
1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的編码表名称。2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储到缓冲区中(编码)。3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)。4.释放资源。
举例:指定编码,将数据保存到文件中。
importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.OutputStreamWriter;public classDemoOutputStreamWriter {public static void main(String[] args) throwsIOException {
Gbk_TXT();
}private static void Gbk_TXT() throwsIOException {//创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的編码表名称。指定编码为GBK。
OutputStreamWriter osw = newOutputStreamWriter(new FileOutputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/OutputStreamWriter.txt"),"gbk");//使用OutputStreamWriter对象中的方法write,把字符转换为字节存储到缓冲区中(编码)。
for (int i = 0; i < 5; i++) {
osw.write("你好!" +i);
osw.write("\n");
}//使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)。
osw.flush();//释放资源。
osw.close();
}
}
运行,生成一个OutputStreamWriter.txt文件,文件内容如下:
由于IDEA默认编码是UTF-8,这里使用了GBK编码格式写入数据进文件,所以在IDEA里面查看文件的内容出现乱码。
InputStreamReader类
java.io.InputStreamReader是字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符(解码)。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
InputStreamReader类是java.io.Reader的子类,所以可以使用父类方法:
public voidclose()//关闭此流并释放与此流相关联的任何系统资源。
public intread()//从输入流读取一个字符。
public int read(char[] chars)//从输入流中读取一些字符,并将它们存储到字符数组chars中。
构造方法
InputStreamReader(InputStream in)//创建默认字符集的InputStreamReader对象
InputStreamReader(InputStream in, String charsetName)//创建指定字符集的InputStreamReader对象
参数:
InputStream in:字符输入流
String charsetName:指定编码表的名称,不区分大小写。如gbk/GBK。
使用步骤:
1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称。2.使用InputStreamReader对象中的方法read,读取文件。3.释放资源。
注意事项:构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码。
举例:按指定解码格式,读取OutputStreamWriter.txt文件的内容
importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStreamReader;public classDemoInputStreamReader {public static void main(String[] args) throwsIOException {
decode_GBK();
}private static void decode_GBK() throwsIOException {//创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称。
InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/OutputStreamWriter.txt"), "GBK");//使用InputStreamReader对象中的方法read,读取文件。
char[] chars = new char[25];while ((isr.read(chars)) != -1) {
System.out.println(chars);
}//释放资源。
isr.close();
}
}
控制台输出:
你好!0你好!1你好!2你好!3你好!4
练习:转换文件编码
将编码GBK编码的文件文本,转换为UTF-8编码的文件文本。
分析:
1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK。2.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8。3.使用InputStreamReader对象中的方法read,读取文件。4.使用OutputStreamWriter对象中的方法write,把读取的数据写入到文件中。5.释放资源。
GBK.txt文件内容如下:
代码实现:
importjava.io.InputStreamReader;importjava.io.OutputStreamWriter;importjava.io.IOException;importjava.io.FileInputStream;importjava.io.FileOutputStream;public classDemoInOutAndReaderWriter {public static void main(String[] args) throwsIOException {
method();
}private static void method() throwsIOException {//创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK。
InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/GBK.txt"), "GBK");//创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/UTF_8.txt"), "UTF-8");//使用InputStreamReader对象中的方法read,读取文件。
int len = 0;while ((len = isr.read()) != -1) {
osw.write(len);
}//释放资源。
isr.close();
osw.close();
}
}
运行生成一个UTF_8.txt文件,文件内容如下: