问题引出:不同编码读取乱码问题
1、之前我们使用字符流读取中文是否有乱码?
没有的,因为创建字符流时如果不指定编码,那么使用的编码是jvm的默认编码,和文件编码都是UTF-8。
Creates a new FileReader, given the name of the file to read, using the platform's default charset.
2、如果jvm的默认编码和文件编码不一致,使用不指定编码的字符流直接读取还能不乱码吗?
会乱码。 文件编码和读取的编码必须一致才不会乱码。
/**
演示一下代码编码与文件编码相同和不同的情况
*/
public class CharSetTest00 {
public static void main(String[] args) {
try (
// 代码:UTF-8 文件 UTF-8 不会乱码
// 1、创建一个文件字符输入流与源文件接通。
// Reader fr = new FileReader("io-app2/src/data01.txt");
// 代码:UTF-8 文件 GBK 乱码. abc 我 爱 你中国
// oo oo
Reader fr = new FileReader("D:\\resources\\data.txt");
// a、把低级的字符输入流包装成高级的缓冲字符输入流。
BufferedReader br = new BufferedReader(fr);
){
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符输入转换流
如何解决jvm默认编码和文件编码不一致,使用字符流直接读取导致乱码呢?
使用字符输入转换流。
可以提取文件(GBK)的原始字节流,原始字节不会存在问题。
然后把字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不乱码。
字符输入转换流
字符输入转换流:InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流。
/**
目标:字符输入转换流InputStreamReader的使用。
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter
字符输入转换流InputStreamReader:
-- 作用:可以解决字符流读取不同编码乱码的问题。
也可以把原始的字节流按照指定编码转换成字符输入流
-- 构造器:
public InputStreamReader(InputStream is):可以使用当前代码默认编码转换成字符流,几乎不用!
public InputStreamReader(InputStream is,String charset):可以指定编码把字节流转换成字符流(核心)
小结:
字符输入转换流InputStreamReader:作用:可以解决字符流读取不同编码乱码的问题。
public InputStreamReader(InputStream is,String charset):可以指定编码把字节流转换成字符流(核心)
*/
public class InputStreamReaderDemo01 {
public static void main(String[] args) throws Exception {
// 代码UTF-8 文件 GBK "D:\\resources\\data.txt"
// 1、提取GBK文件的原始字节流。 abc 我
// ooo oo
InputStream is = new FileInputStream("D:\\resources\\data.txt");
// 2、把原始字节流转换成字符输入流
// Reader isr = new InputStreamReader(is); // 默认以UTF-8的方式转换成字符流。 还是会乱码的 跟直接使用FileReader是一样的
Reader isr = new InputStreamReader(is , "GBK"); // 以指定的GBK编码转换成字符输入流 完美的解决了乱码问题
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
}
字符输出转换流
如果需要控制写出去的字符使用的编码,怎么办?
可以把字符以指定编码获取字节后再使用字节输出流写出去: “我爱你中国”.getBytes(编码) ,
也可以使用字符输出转换流实现。
字符输出转换流
字符输入转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流。
/**
目标:字符输出转换OutputStreamWriter流的使用。
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter
字符输出转换流:OutputStreamWriter
-- 作用:可以指定编码把字节输出流转换成字符输出流。
可以指定写出去的字符的编码。
-- 构造器:
public OutputStreamWriter(OutputStream os) : 用当前默认编码UTF-8把字节输出流转换成字符输出流
public OutputStreamWriter(OutputStream os , String charset):指定编码把字节输出流转换成字符输出流
小结:
字符输出转换流OutputStreamWriter可以指定编码把字节输出流转换成字符输出流。
从而实现指定写出去的字符编码!
*/
public class OutputStreamWriterDemo02 {
public static void main(String[] args) throws Exception {
// 1、定义一个字节输出流
OutputStream os = new FileOutputStream("io-app2/src/out03.txt");
// 2、把原始的字节输出流转换成字符输出流
// Writer osw = new OutputStreamWriter(os); // 以默认的UTF-8写字符出去 跟直接写FileWriter一样
Writer osw = new OutputStreamWriter(os , "GBK"); // 指定GBK的方式写字符出去
// 3、把低级的字符输出流包装成高级的缓冲字符输出流。
BufferedWriter bw = new BufferedWriter(osw);
bw.write("我爱中国1~~");
bw.write("我爱中国2~~");
bw.write("我爱中国3~~");
bw.close();
}
}