黑马程序员-Java I/O流(一)-IO流概述、字符流、字节流、流操作规律

来源:互联网 发布:yum 删除 package 编辑:程序博客网 时间:2024/05/21 03:25

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

1. 概述
流:可以理解数据的流动,就是一个数据流。Java中与IO相关的类有很多,都集中在java.io中,都是以流的形式操作的,它的本质是传输数据。
IO流分类:
(1)根据数据类型的不同可以分为字节流和字符流。
(2)根据流向的不同可以分为输入流和输出流。

Java 中所有IO流的关系如下图:

主要的操作流程如下:
1使用File类打开一个文件
2 通过字节流或字符流的子类,指定输出的位置
3 进行读/写操作
4 关闭输入/输出

2. 字符流 Reader Writer
以Unicode字符为导向的stream,表示以Unicode字符为单位从stream中读取或往stream 中写入信息。
Reader/Writer 为abstact类

Reader:以Unicode字符为导向的流,以Unicode字符为单位从流中读取,是一个抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。
Reader的常用读取操作:
1.int read() 读取单个字符。
2.int read(char[] cbuf) 将字符读入数组。
3.abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。

在使用Reader进行数据流的读入操作时是不会直接创建Reader对象的,一般都是使用其子类,如FileReader,示例代码如下:

import java.io.*;class  FileReaderDemo {    public static void main(String[] args) throws IOException       {        //创建可以读取文本文件的流对象,FileReader让创建好的流对象和指定的文件相关联。        //读取demo.txt数据,一次读一个字符,返回字符的十进制形式。        FileReader fr = new FileReader("demo.txt");        int ch = 0;        while((ch = fr.read())!= -1) { //条件是没有读到结尾            System.out.println((char)ch); //调用读取流的read方法,读取一个字符。        }        fr.close();    }}

读取的第二种形式是添加一个自定义缓冲区,这种方法比较高效。

import java.io.*;class FileReaderDemo {    public static void main(String[] args) throws IOException {         //读取demo.txt数据。    FileReader fr = new FileReader("demo.txt");     //设定一个字符数组为缓冲区,使用read(char[])方法,将读取到字符存入数组,字符数组的长度都是1024的整数倍。        char[] buf = new char[1024];//缓冲区        int len = 0;        while(( len=fr.read(buf)) != -1) {            System.out.println(new String(buf,0,len));        }        fr.close();    }}

上面代码需要注意是,不管是流的创建,打开,写入,读取,刷新,关闭等操作,一般都会抛出IOException,因为对磁盘进行操作(一般都是)都有可能产生错误,如磁盘满了,文件被占用等等,所以必须对其进行捕获,并处理。流的关闭一般放在try中的finally中,原因是为防止出错后无法及时释放资源。

Writer : 以Unicode字符为导向的流,以Unicode字符为单位往流中写入,是一个抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。
Writer的常用写入操作:
1.abstract void flush() 刷新该流的缓冲。
2.void write(char[] cbuf) 写入字符数组。
3.void write(int c) 写入单个字符。
4.void write(String str) 写入字符串。
5.void write(String str, int off, int len) 写入字符串的某一部分。

在使用Writer进行数据流的读入操作时是不会直接创建Writer对象的,一般都是使用其子类,如FileWriter,示例代码如下:

import java.io.*;class FileDWriterdemo {public static void main(String[] args) {  /*  创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。    而且该文件会被创建到指定目下, 其实该步骤就是在明确数据要存放的目的地。 */        FileWriter fw = null;               try {            fw = new FileWriter("demo.txt",true);//传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处进行数据续写。            fw.write("aaa");//调用write()方法,将字符串写入到流中。        }        catch (IOException e ){            System.out.println(e.toString()+"....");        }        finally{            if(fw!=null)                try{                    fw.close();                }                catch (IOException e){                    System.out.println("close:"+e.toString());                }        }}

需要注意的是:流的关闭一般放在try中的finally中,原因是为防止出错后无法及时释放资源。在进行数据的写入时,当执行完write方法后,数据可能不会立即被写入到目的地,这时可以使用flush功能进行立即完成写入功能,也可以在close时自定完成内容的写入。

字符缓冲流BufferedWriter和BufferedReader:
为了提程序效率,java设置了Writer和Reader对应的类:BufferedReader和BufferedWriter,下面是一个示例:

import java.io.*;class BufferedDemo {    public static void main(String[] args) {        BufferedWriter bw = null;        try {        //创建一个写入流对象,并且用缓冲流对象指定该写入流            bw = new BufferedWriter(new FileWriter("file.txt"));            bw.write("Test");//将"test"写入            bw.newLine();//写入换行标志            bw.flush();        } catch (IOException e) {            // IO异常在这里处理        } finally {            try {                // 在finally中关闭流,并判断是否为null                if(bw != null) {                    bw.close();                }            } catch (IOException e) {}        }    }}

3. 字节流 InputStream OutputStream

字符流操作的是纯文本内容,而字节流则是所有二进制文件都可以操作,如图片,视频,当然文件文件也是可以的。与字符流中读出和写入的类型为char型相对应,字节流读出和写入的是byte类型。字节流的两个基本输入输出流为InputStream和OutputStream,其功能与字符流的功能类似。对于文件的操作的流是相应的FileInputStream和FileOutputStream,下面通过一个图片拷贝功能作为字节流的一个示例代码:

import java.io.*;class putStreamDemo {    public static void main(String[] args) throws IOException {        FileInputStream fin = new FileInputStream("pic1.png");        FileOutputStream fout = new FileOutputStream("pic2.png");        // 与Reader不同的是这里使用的是byte类型        byte[] buf = new byte[1024];        int n = 0;        while((n=fin.read(buf)) != -1) {            fout.write(buf, 0, n);//字节流写入        }        // 关闭流        fin.close();        fout.close();    }}

我们注意到字节流不能直接写入,需要转化成字节数组进行写入和输出。

字节缓冲流BufferedInputStream和BufferedOutputStream:

import java.io.*;class Demo {    public static void main(String[] args) throws IOException {        BufferedInputStream bi =             new BufferedInputStream(new FileInputStream("pic1.png"));        BufferedOutputStream bo =             new BufferedOutputStream(new FileOutputStream("pic2.png"));    int data = 0;        while((data = bi.read()) != -1) {            bo.write(data);        }        bi.close();        bo.close();    }}

未加入缓冲机制时候,每次read()都会调用系统底层读取磁盘的操作,读取一个字节,非常耗时;而加入缓冲机制后,系统会一次将很多内容读取到内存,而调用read()时,只需要从内存中返回数据内容即可,大大减少了系统底层访问磁盘的次数,所以速度会加快很多。

读取转换流和写入转换流 InputStreamReader和OutputStreamWriter:
为了方便了字符流与字节流之间的操作,当我们读取键盘(System.in)数据时,便可以使用InputStreamReader,当我们将数据输出到控制台(System.out),便可以使用OutputStreamWriter,示例代码如下:

import java.io.*;class Demo {    public static void main(String[] args) throws IOException {        // 键盘的最常见写法。        BufferedReader bfr =                 new BufferedReader(new InputStreamReader(System.in));        // 使用字符输出方式到控制台        BufferedWriter bfw =                 new BufferedWriter(new OutputStreamWriter(System.out));        String line = null;        while((line=bfr.readLine()) != null) {            bfw.write(line.toUpperCase());//将输入的字符转成大写字符输出            bfw.newLine();            bfw.flush();        }        bfr.close();        bfw.close();    }}

4. 流操作规律 :
(1)明确源和目的。
数据源:就是需要读取,可以使用两个体系:InputStream、Reader;
数据汇:就是需要写入,可以使用两个体系:OutputStream、Writer;
(2)操作的数据是否是纯文本数据?
如果是:数据源:Reader
数据汇:Writer
如果不是:数据源:InputStream
数据汇:OutputStream
(3)虽然确定了一个体系,但是该体系中有太多的对象,到底用哪个呢?
明确操作的数据设备。
数据源对应的设备:硬盘(File),内存(数组),键盘(System.in)
数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)。
(4)需要在基本操作上附加其他功能吗?比如缓冲。
如果需要就进行装饰。

0 0
原创粉丝点击