字符编码
计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符时二进制数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符合。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。
编码:字符(能看懂的)–字节(看不懂的)
解码:字节(看不懂的)–字符(能看懂的)
字符编码Character Encoding:就是一套自然语言的字符与二进制数之间的对应规则。
编码表:生活中文字和计算机中二进制的对应规则
字符集
在IDEA中,使用FileReader,读取项目中的文本文件。由于IDEA的设置,都是默认的UTF-8编码,所以没有任何问题。但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。
代码演示如下:
package com.io.reversestream;
import java.io.FileReader;
import java.io.IOException;
/*
FileReader可以读取IDE默认编码格式(UTF-8)的文件
FileReader读取系统默认编码(中文GBK)会产生乱码
*/
public class ReverseStreamDemo01 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("C:\\abc\\我是GBK格式的文本.txt");
int len = 0;
while ((len = fr.read())!=-1){
System.out.println((char) len);
}
fr.close();
}
}
那么如何读取GBK编码的文件呢?
转换流java.io.InputStreamReader,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接收平台的默认字符集。
InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset
将其解码为字符 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
每个调用InputStreamReader的read()方法之一可能会导致从底层字节输入流读取一个或多个字节。 为了使字节有效地转换为字符,可以从底层流读取比满足当前读取操作所需的更多字节。
为了最大的效率,请考虑在BufferedReader中包装一个InputStreamReader。 例如:
BufferedReader in
= new BufferedReader(new InputStreamReader(System.in));
构造方法
InputStreamReader(InputStream in):创建一个使用默认字符集的字符流。
InputStreamReader(InputStream in, String charsetName):创建一个使用命名字符集的字符流。
构造举例,代码如下:
InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt"),"GBK");
代码实例:
package com.io.reversestream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/*
java.io.InputStreamReader extends Reader
InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset将其解码为字符 。
构造方法:
InputStreamReader(InputStream in)创建一个使用默认字符集的InputStreamReader。
InputStreamReader(InputStream in, String charsetName)创建一个使用命名字符集的InputStreamReader。
参数:
inputStream in:字符输入流,用来读取文件中保存的字节
String charsetName:指定的编码表名称,不区分大小写,不指定默认utf-8
使用步骤:
1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
2.使用InputStreamReader对象中的方法read读取文件
3.释放资源。
注意事项:
构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码
*/
public class InputStreamReaderDemo01 {
public static void main(String[] args) throws IOException {
read_utf_8();
}
/*
使用InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
*/
private static void read_utf_8() throws IOException {
//1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\abc\\utf_8.txt"));
//2.使用InputStreamReader对象中的方法read读取文件
int len = 0;
while ((len = isr.read())!=-1){
System.out.println((char) len);
}
//3.释放资源
isr.close();
}
}
OutputStreamWriter是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节charset
。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
每次调用write()方法都会使编码转换器在给定字符上被调用。 所得到的字节在写入底层输出流之前累积在缓冲区中。 可以指定此缓冲区的大小,但是默认情况下它大部分用于大多数目的。 请注意,传递给write()方法的字符不会缓冲。
为了最大的效率,请考虑在BufferedWriter中包装一个OutputStreamWriter,以避免频繁的转换器调用。 例如:
Writer out
= new BufferedWriter(new OutputStreamWriter(System.out));
构造方法
代码实例:
package com.io.reversestream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/*
java.io.OutputStreamWriter extends Writer
OutputStreamWriter是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节charset 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
构造方法:
OutputStreamWriter(OutputStream out)创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName)创建一个使用命名字符集的OutputStreamWriter。
参数:
OutputStream out:字节输出流,可以用来写转换之后的字节到文件中
String charsetName:指定的编码表名称,不区分大小写,可以是utf-8等不指定默认使用Utf-8
使用步骤:
1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
4.释放资源。
*/
public class OutputStreamWriterDemo01 {
public static void main(String[] args) throws IOException {
//write_utf_8();
write_gbk();
}
/*
使用转换流OutputStreamWriter写GBK格式的文件
*/
private static void write_gbk() throws IOException {
//1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\abc\\gbk.txt"), "GBK");
//2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
osw.write("你好");
//3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
osw.flush();
//4.释放资源
osw.close();
}
/*
使用转换流OutputStreamWriter写UTF-8格式的文件
*/
private static void write_utf_8() throws IOException {
//1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\abc\\utf_8.txt"), "utf-8");
//2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
osw.write("你好");
//3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
osw.flush();
//4.释放资源
osw.close();
}
}
将GBK编码的文本文件,转换成UTF-8编码的文本文件。
代码实例
package com.io.reversestream;
import java.io.*;
/*
练习:转换文件编码
将GBK编码的文本文件,转换为UTF-8编码文件。
分析:
1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK
2.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8
3.使用InputStreamReader对象中方法read读取文件
4.使用OutputStreamWriter对象中的方法write,把读取的数据写入到文件中
5.释放资源
*/
public class TransDemo01 {
public static void main(String[] args) throws IOException {
//1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK
InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\abc\\gbk.txt"));
//2.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\abc\\utf_8.txt"));
//3.使用InputStreamReader对象中方法read读取文件
int len = 0;
while ((len = isr.read())!=-1){
//4.使用OutputStreamWriter对象中的方法write,把读取的数据写入到文件中
osw.write(len);
}
//5.释放资源
osw.close();
isr.close();
}
}