Java笔记 - IO流 - 转换流

1. InputStreamReader
目的:
获取用户键盘录入的数据,并将数据变成大写显示在控制台上,如果用户输入over,结束键盘录入。
在这里,因为输入的是文本内容,并且是一行一行的,所以使用readLine()方法来操作应该是最方便的。但是readLine()是字符输入流BufferedReader类中的方法,而System.in是一个InputStream类型的字节流,所以就要想办法在他们之间搭建起桥梁,把字节流转换为字符流。这个桥梁就是InputStreamReader类,它是Reader类的一个子类。

//字节流
InputStream in = System.in;
//转换流
InputStreamReader isr = new InputStreamReader(in);
//字符流
BufferedReader bufr = new BufferedReader(isr);

String line = null;
while ((line = bufr.readLine())!= null) {
    if (line.equals("over")) {
        break;
    }else{
        System.out.println(line.toUpperCase());
    }
}

输出结果:

haha
HAHA
xixi
XIXI
hehe
HEHE
over

输入over后程序停止。

使用字节流读一个中文需要读两次,使用字符流读一个中文只需要读一次

//字节流
InputStream in = System.in;
int ch = in.read();
System.out.println(ch);
int ch1 = in.read();
System.out.println(ch1);

输出结果:

你
196
227
//字节流
InputStream in = System.in;
//转换流
InputStreamReader isr = new InputStreamReader(in);
int ch = isr.read();
System.out.println(ch);

输出结果:

你
20320

2. OutputStreamWriter
InputStreamReader是字节流通向字符流的桥梁,与之相对应的,还有一个字符流通向字节流的桥梁OutputStreamWriter类,它是Writer类的子类。
字符 —>字节:编码
字节 —>字符:解码

System.out是标准输出流。它是PrintStream类型的,PrintStream是字节输出流OutputStream的子类,我们平时使用的println()方法就是该类的方法。
刚才我们将输入的内容变成大写打印在控制台的语句是:

System.out.println(line.toUpperCase());

我们获取到的是字符,但是控制台只能够接收字节数据。所以现在我们想自己实现将字符打印到控制台的这个过程,就需要一个能够把字符转变成字节的对象,就是OutputStreamWriter。

//字节流
InputStream in = System.in;
//转换流
InputStreamReader isr = new InputStreamReader(in);
//字符流
BufferedReader bufr = new BufferedReader(isr);
//字节流   
OutputStream os = System.out;//父类引用指向子类对象,多态。
//转换流
OutputStreamWriter osw = new OutputStreamWriter(os);
//字符流       
BufferedWriter  bufw = new BufferedWriter(osw);

String line = null;
while ((line = bufr.readLine())!= null) {
    if (line.equals("over")) {
        break;
    }else{
        bufw.write(line.toUpperCase());
        bufw.newLine();
        bufw.flush();
    }
}

输出结果:

haha
HAHA
xixi
XIXI
hehe
HEHE
over

3. 流的操作规律
IO流有很多对象,在开发的时候我们不知道到底使用哪个对象合适,这时候只要知道四个明确即可。

1.明确源和目的(汇)
源:InputStream Reader
目的:OutputStream Writer

2.明确数据是否是纯文本数据
源:是纯文本:Reader
不是纯文本:InputStream
目的:是纯文本:Writer
不是纯文本:OutputStream

到这里就可以明确具体要使用哪个体系

3.明确具体设备
源设备:
- 硬盘:File
- 键盘:System.in
- 内存:数组
- 网络:Socket流

目的设备:
- 硬盘:File
- 键盘:System.out
- 内存:数组
- 网络:Socket流

4.是否需要其他额外功能
需要高效:缓冲区,加buffer
需要转换:InputStreamReader或OutputStreamWriter

4.转换流的编码与解码
如果想将一个字符串数据写入到一个文本文件中,之前我们是这么做的

FileWriter fw = new FileWriter("E:\\a.txt");
fw.write("你好");
fw.flush();
fw.close();

输出结果:

你好//4字节

这时其实使用的是默认的码表,如果我们想指定编码表应该怎么办?

Java内置的是Unicode码表,对于字符类型的数据都是用Unicode码表来解析的,也就是说,任何Java识别的字符数据用的全是Unicode码表,但是字符串用的是本地码表GBK。Unicode不管是什么文字,都统一用两个字节来表示,但这样对ASCII来说,高位字节毫无意义。后期为了优化,于是出现了Unicode Transformation Format-8,简称UTF-8。它一个字节能装下的字符就用一个字节装,一个字节能装不下就用两个字节装,两个字节装不下就用三个字节装。
现在准备使用UTF-8来进行存储。这时候转换流最大的好处就体现出来了,因为转换流可以在构造函数中加入编码表。OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

FileWriter类使用的是默认的字符编码,它是转换流OutputStreamWriter的子类。

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\b.txt"),"UTF-8");
osw.write("你好");
osw.flush();
osw.close();

输出结果:

你好//6字节

其实
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“gbk_1.txt”),”GBK”);

FileWriter fw = new FileWriter(“gbk_2.txt”);
这两句话是等同的,FileWriter其实就是转换流指定了本机默认码表,简单说,就是操作文件的字节流+本机默认的编码表。这是按照默认码表来操作文件的便捷类。之前我们说字符流是字节流+编码表,具体说就是字符流中的转换流。

并且如果想要读取UTF-8编码的文件,解码也要用UTF-8

InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\c.txt"),"UTF-8");
char[] buf = new char[1024];
int len = isr.read(buf);
String str = new String(buf,0,len);
System.out.println(str);

输出结果:

你好

你可能感兴趣的:(java)