IO【字节流、高效流】


第11天 IO流
今日内容介绍
    字节流
    缓冲流
今日学习目标
    可以使用字节输出流写出数据到文件
    可以使用字节输入流读取数据到程序
    可以理解读取数据read(byte[])方法的原理
    可以使用字节流完成文件的复制
    可以使用字节缓冲流读取数据到程序
    可以使用字节缓冲流写出数据到文件
    可以完成单级文件夹复制
第1章    IO
1.1    IO概述
回想以前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,但是已经没有了。那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再把这些数据读出来继续使用呢?其实要把数据持久化存储,就须要把内存中的数据存储到内存之外的其余持久化设备(硬盘、光盘、U盘等 ROM)上。
当须要把内存中的数据存储到持久化设备上这个动做称为输出(写)Output操做。
当把持久设备上的数据读取到内存中的这个动做称为输入(读)Input操做。
所以咱们把这种输入和输出动做称为IO操做。数组


1.2    IO流流向分类
按照流向分:输入流与输出流,每一个IO流对象均要绑定一个IO资源
分类关系以下:
字节输入流 InputStream 抽象类
FileInputStream 操做文件的字节输入流
字节输出流 OutputStream 抽象类
FileOutputStream 操做文件的字节输出流
按照传输方式:分为字节流和字符流
   字符流  按照字符的方式读写
   字节流  按照字节的方式读写

1.3    一切均为字节
在数据传输过程当中,一切数据(文本、图像、声音等)最终存储的均为一个个字节,即二进制数字。因此数据传输过程当中使用二进制数据能够完成任意数据的传递。
为何打开一个文本文件 咱们看到的不是0101001这些数据?
咱们向一个文件中存储必定的数据(一些数字),若是使用文本方式打开,则会以文本的方式解释数据。若是以视频的方式打开,则会以视频的方式解释数据。音频、可行执行文件等亦是如此。因此,在文件传输过程当中,咱们要时刻明确,传输的始终为二进制数据。函数

第2章    字节流
既然一切数据都是字节,那么字节流如何操做呢,那么接下来咱们进行字节流的学习.
2.1    字节输出流OutputStream
OutputStream此抽象类,是表示输出字节流的全部类的超类。操做的数据都是字节,定义了输出字节流的基本共性功能方法。
输出流中定义都是写write方法,以下图:学习


2.1.1    FileOutputStream类
OutputStream有不少子类,其中子类FileOutputStream可用来写入数据到文件。
FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流。spa

    构造方法code

2.1.2    FileOutputStream类写入数据到文件中(三个方法)
    将数据写到文件中,
    步骤
    1.建立输出流对象
    2.调用输出流对象的写数据方法
    3.释放资源
    代码演示:视频

public class FileOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //需求:将数据写入到文件中。
        //建立存储数据的文件。
        File file = new File("c:\\file.txt");
        //建立一个用于操做文件的字节输出流对象。一建立就必须明确数据存储目的地。
        //输出流目的是文件,会自动建立。若是文件存在,则覆盖。
        FileOutputStream fos = new FileOutputStream(file);
        //调用父类中的write方法。
        byte[] data = "abcde".getBytes();
        fos.write(data);
        //关闭流资源。
        fos.close();
    }
}

2.1.3    给文件中续写和换行
咱们直接new FileOutputStream(file)这样建立对象,写入数据,会覆盖原有的文件,那么咱们想在原有的文件中续写内容怎么办呢?
继续查阅FileOutputStream的API。发如今FileOutputStream的构造函数中,能够接受一个boolean类型的值,若是值true,就会在文件末位继续添加。
    构造方法对象


    给文件中续写数据和换行,代码演示:blog

public class FileOutputStreamDemo2 {
    public static void main(String[] args) throws Exception {
        File file = new File("c:\\file.txt");
        FileOutputStream fos = new FileOutputStream(file, true);
        String str = "\r\n"+"itcast";
        fos.write(str.getBytes());
        fos.close();
    }
}

2.2    字节输入流InputStream
经过前面的学习,咱们能够把内存中的数据写出到文件中,那如何想把内存中的数据读到内存中,咱们经过InputStream能够实现。InputStream此抽象类,是表示字节输入流的全部类的超类。,定义了字节输入流的基本共性功能方法。内存


    int read():读取一个字节并返回,没有字节返回-1.
    int read(byte[]): 读取必定量的字节数,并存储到字节数组中,返回读取到的字节数。
2.2.1    FileInputStream类
InputStream有不少子类,其中子类FileInputStream可用来读取文件内容。
FileInputStream 从文件系统中的某个文件中得到输入字节。资源


    构造方法


2.2.2    FileInputStream类读取数据read方法(只读纯英文,有空介绍一下读中文问题)
在读取文件中的数据时,调用read方法,实现从文件中读取数据


    从文件中读取数据,代码演示:

public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("c:\\file.txt");
        //建立一个字节输入流对象,必须明确数据源,其实就是建立字节读取流和数据源相关联。
        FileInputStream fis = new FileInputStream(file);
        //读取数据。使用 read();一次读一个字节。
        int ch = 0;
        while((ch=fis.read())!=-1){
            System.out.println("ch="+(char)ch);
        }
        // 关闭资源。
        fis.close();
    }
}

2.2.3    读取数据read(byte[])方法
在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,因而咱们能够定义数组做为临时的存储容器,这时能够调用重载的read方法,一次能够读取多个字符。

public class FileInputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        /*          * 演示第二个读取方法, read(byte[]);          */
        File file = new File("c:\\file.txt");
        // 建立一个字节输入流对象,必须明确数据源,其实就是建立字节读取流和数据源相关联。
        FileInputStream fis = new FileInputStream(file);        
        //建立一个字节数组。
        byte[] buf = new byte[1024];//长度能够定义成1024的整数倍。      
        int len = 0;
        while((len=fis.read(buf))!=-1){
            System.out.println(new String(buf,0,len));
        }
        fis.close();
    }
}

2.3    字节流练习
既然会了文件的读和写操做了,那么咱们就要在这个基础上进行更为复杂的操做。使用读写操做完成文件的复制。
2.3.1    复制文件
原理;读取一个已有的数据,并将这些读到的数据写入到另外一个文件中。

public class CopyFileTest {
    public static void main(String[] args) throws IOException {
        //1,明确源和目的。
        File srcFile = new File("c:\\YesDir\test.JPG");
        File destFile = new File("copyTest.JPG");

        //2,明确字节流 输入流和源相关联,输出流和目的关联。
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);

        //3, 使用输入流的读取方法读取字节,并将字节写入到目的中。
        int ch = 0;
        while((ch=fis.read())!=-1){
            fos.write(ch);
        }
        //4,关闭资源。
        fos.close();
        fis.close();
    }
}

上述代码输入流和输出流之间是经过ch这个变量进行数据交换的。
上述复制文件有个问题,每次都从源文件读取一个,而后在写到指定文件,接着再读取一个字符,而后再写一个,一直这样下去。效率极低。
2.3.2    临时数组方式复制文件
上述代码复制文件效率过低了,而且频繁的从文件读数据,和写数据,能不能一次多把文件中多个数据都读进内容中,而后在一次写出去,这样的速度必定会比前面代码速度快。

public class CopyFileByBufferTest {
    public static void main(String[] args) throws IOException {
        File srcFile = new File("c:\\YesDir\test.JPG");
        File destFile = new File("copyTest.JPG");
        // 明确字节流 输入流和源相关联,输出流和目的关联。
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);
        //定义一个缓冲区。
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
            fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
        }
        // 关闭资源。
        fos.close();
        fis.close();
    }
}

第3章    缓冲流
在咱们学习字节流与字符流的时候,你们都进行过读取文件中数据的操做,读取数据量大的文件时,读取的速度会很慢,很影响咱们程序的效率,那么,我想提升速度,怎么办?
Java中提升了一套缓冲流,它的存在,可提升IO流的读写速度
缓冲流,根据流的分类分类字节缓冲流与字符缓冲流。
在基础班咱们已经学习过字符缓冲流了,那么今天学习一下字节缓冲流。
3.1    字节缓冲流
字节缓冲流根据流的方向,共有2个
    写入数据到流中,字节缓冲输出流 BufferedOutputStream
    读取流中的数据,字节缓冲输入流 BufferedInputStream

它们的内部都包含了一个缓冲区,经过缓冲区读写,就能够提升了IO流的读写速度
3.1.1    字节缓冲输出流BufferedOutputStream
经过字节缓冲流,进行文件的读写操做 写数据到文件的操做  
    构造方法
public BufferedOutputStream(OutputStream out)建立一个新的缓冲输出流,以将数据写入指定的底层输出流。

public class BufferedOutputStreamDemo01 {
    public static void main(String[] args) throws IOException {

        //写数据到文件的方法
        write();
    }

    /*      * 写数据到文件的方法      * 1,建立流      * 2,写数据      * 3,关闭流      */
    private static void write() throws IOException {
        //建立基本的字节输出流
        FileOutputStream fileOut = new FileOutputStream("abc.txt");
        //使用高效的流,把基本的流进行封装,实现速度的提高
        BufferedOutputStream out = new BufferedOutputStream(fileOut);
        //2,写数据
        out.write("hello".getBytes());
        //3,关闭流
        out.close();
    }
}

3.1.2    字节缓冲输入流 BufferedInputStream
刚刚咱们学习了输出流实现了向文件中写数据的操做,那么,如今咱们完成读取文件中数据的操做
    构造方法
public BufferedInputStream(InputStream in)

    /*      * 从文件中读取数据      * 1,建立缓冲流对象      * 2,读数据,打印      * 3,关闭      */
    private static void read() throws IOException {
        //1,建立缓冲流对象
        FileInputStream fileIn = new FileInputStream("abc.txt");
        //把基本的流包装成高效的流
        BufferedInputStream in = new BufferedInputStream(fileIn);
        //2,读数据
        int ch = -1;
        while ( (ch = in.read()) != -1 ) {
            //打印
            System.out.print((char)ch);
        }
        //3,关闭
        in.close();
    }

3.1.3    复制单级文件夹

/*   * 数据源:e:\\demo  * 目的地:e:\\test  *   * 分析:  *         A:封装目录  *         B:获取该目录下的全部文本的File数组  *         C:遍历该File数组,获得每个File对象  *         D:把该File进行复制  */
public class CopyFolderDemo {
    public static void main(String[] args) throws IOException {
        // 封装目录
        File srcFolder = new File("e:\\demo");
        // 封装目的地
        File destFolder = new File("e:\\test");
        // 若是目的地文件夹不存在,就建立
        if (!destFolder.exists()) {
            destFolder.mkdir();
        }

        // 获取该目录下的全部文本的File数组
        File[] fileArray = srcFolder.listFiles();

        // 遍历该File数组,获得每个File对象
        for (File file : fileArray) {
            // System.out.println(file);
            // 数据源:e:\\demo\\e.mp3
            // 目的地:e:\\test\\e.mp3
            String name = file.getName(); // e.mp3
            File newFile = new File(destFolder, name); // e:\\test\\e.mp3

            copyFile(file, newFile);
        }
    }

    private static void copyFile(File file, File newFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                file));
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream(newFile));

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        bis.close();
    }
} 

欢迎关注菜鸟永恒,天天进步一小点。