节点流(文件流)

节点流

FileReader和FileWriter

字符流(cha[]数组)

FileReader读入数据的基本操作

过程

  1. 实例化File类的对象,指明要操作的文件

    注意:

    • 在@Test测试中的相对路径是相对于当前Module

    • 在main函数的相对路径是相对于当前工程

  2. 提供具体的流

  3. 数据的读入过程

  4. 流的关闭操作

  5. try-catch-finally异常处理

说明

  • 一定要注意最后流的关闭
  • read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
  • 异常的处理:为了保证流资源一定可以执行关闭的操作,需要使用try-catch-finally来处理
  • 读入的文件(hello.txt)一定要存在,否则会报FileNotFoundException异常

代码实现

@org.junit.Test
public void test1(){
    FileReader fileReader = null;
    try {
        //1. 实例化File类的对象,指明要操作的文件
        //注意:在@Test测试中的相对路径是相对于当前Module,在main函数的相对路径是相对于当前工程
        File file = new File("hello.txt");//相对路径

        //2. 提供具体的流
        fileReader = new FileReader(file);

        //3. 数据的读入过程
        //read():返回读入的一个字符。如果达到文件末尾,返回-1
        //方式一
//      int data = fileReader.read();
//      while(data != -1){
//          System.out.print((char)data);
//          data = fileReader.read();
//      }

        //方式二:语法上针对方式一的修改
        int data;
        while((data = fileReader.read()) != -1){
            System.out.println((char)data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        //4. 流的关闭操作
        try {
            //防止最开始提供流是出现异常导致这里是空指针,所以加一个判断
            if(fileReader != null){
                fileReader.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果

此时的"hello.txt"文档中存储的内容是hello

o6Ij4.png

使用read()的重载方法

  • read():返回读入的一个字符。如果达到文件末尾,返回-1
  • read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1(常用)
  • read(char cbuf[], int off, int len) (不常用)
read(char[] cbuf)的用法
  1. 创建一个char的数组cbuf

    (举例假定该数组的长度为5)

    char[] cbuf = new char[5];

  2. 创建len变量,存储read(char[] cbuf)的返回值

    (注意:返回值即为每次读入cbuf数组中的字符的个数)

  3. 读取数据

    • 写法一:循环遍历
    for (int i = 0; i < len; i++) {
        System.out.print(cbuf[i]);
    }
    
    • 写法二:char[]类型和String类型转换
    String str = new String(cbuf,0,len);
    System.out.print(str);
    

    https://www.cnblogs.com/CrabDumplings/p/13341279.html

    o91I2.png

  4. 流的关闭操作(不要忘记)

read(char[] cbuf)读取数据时的注意事项
  • 写法一

    for (int i = 0; i < len; i++) {
        System.out.print(cbuf[i]);
    }
    

    其中for循环时,i一定要小于len(每次读入cbuf数组中的字符的个数)而不是cbuf.length

    • 画图说明:

      o9xOe.png

      最后还剩下3个数据的时候:

      • 如果for循环中的i小于cbuf.length(错误的写法)

        o9rpk.png

        最后的输出为:helloWorld123ld

        (其中hello为第一次的结果,World为第二次的结果,123ld为第三次的结果)

        而文件中的内容为helloWorld123,所以此时的写法是错误的

      • 如果for循环中的i小于len(正确的写法)
        o9Ogn.png

        最后的输出为:helloWorld123

        (其中hello为第一次的结果,World为第二次的结果,123为第三次的结果)

  • 写法二

    String str = new String(cbuf,0,len);
    System.out.print(str);
    

    其中利用了String(char[] value, int offset, int count)构造器,而不是String(char[] value)构造器

    • String(char[] value)构造器(错误的写法)
      错误原因与写法一错误的方法相同

    • String(char[] value, int offset, int count)构造器(正确的写法)

      读取char[]数组中角标0到角标len的内容,过程与写法一正确的方法过程类似

FileReader写出数据的基本操作

过程

  1. 实例化File类的对象,指明要操作的文件
  2. 提供具体的流
  3. 数据的写出过程
  4. 流的关闭操作
  5. try-catch-finally异常处理

说明

写出操作,对应的File可以不存在。

  • 如果不存在,在写出的过程中,会自动创建此文件
  • 如果存在这个文件
    • 对原有文件的覆盖

      流使用的构造器为

      FileWriter(file, false)

      或者是

      FileWriter(file)

    • 在原有文件的基础上追加内容(不会对原有文件进行覆盖)

      流使用的构造器为

      FileWriter(file, true)

o9TfM.png

代码实现

FileWriter fw1 = null;
FileWriter fw2 = null;
try {
    //1. 提供File类的对象,指明写出到的文件
    File file = new File("hi.txt");

    //2. 提供FileWriter的对象,用于文件的写出
    //覆盖
    fw1 = new FileWriter(file,false);
    //不覆盖
    fw2 = new FileWriter(file,true);
    //3. 写出的操作
    fw1.write("I have a dream!\n");
    fw2.write("123\n");
} catch (IOException e) {
    e.printStackTrace();
}finally {
    //4. 关闭流资源
    if(fw1 != null)
        try {
            fw1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fw2 != null)
                try {
                    fw2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        } 
}

运行结果

最开始hi.txt文件中的内容为hello
运行代码后
o9VQa.png

使用FileWriter和FileReader实现文本文件的复制

过程

  1. 创建File类的对象,指明读入和写出的文件
  2. 创建输入流和输出流的对象
  3. 数据的读入和写入操作
  4. 关闭流资源
  5. try-catch-finally异常处理

说明

  • 在读取文件文件时,选择read(char[] cbuf)的用法

  • 在写入文件的时候,注意不要写成

    fw.write(cbuf);

    此时出现的错误和读取操作时写法一会出现的错误相同,不可以正确的读取文件中原本的内容

    需要使用

    fw.write(cbuf,0,len);

    读取cbuf数组中角标为0的元素到角标为len的元素

  • 在最后关闭流资源的时候,一定要注意两个流都要关闭,即使其中一个流在关闭的时候抛出异常另一个流也要关闭

    有两种写法

    • 写法一
    finally {
        //4. 关闭流资源
        if(fr != null)
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(fw != null)
                    try {
                        fw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
    }
    
    • 写法二
    finally {
        //4. 关闭流资源
        try {
            if(fr != null)
                fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        try {
            if(fw != null)
                fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

代码实现

public void test4(){
    FileReader fr = null;
    FileWriter fw = null;
    try {
        //1. 创建File类的对象,指明读入和写出的文件
        File file1 = new File("hello.txt");
        File file2 = new File("hi.txt");
        //2. 创建输入流和输出流的对象
        fr = new FileReader(file1);
        fw = new FileWriter(file2,true);
        //3. 数据的读入和写入操作
        char[] cbuf = new char[5];
        int len;//记录每次读入到cbuf数组中字符的个数
        while((len = fr.read(cbuf)) != -1){
            //每次写出len个字符
            fw.write(cbuf,0,len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        //4. 关闭流资源
        try {
            if(fr != null)
                fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            if(fw != null)
                fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果

oG51G.png

注意

字符流不能处理图片文件等字节数据!!!

FileInputStream和FileOutputStream

字节流(byte[])

使用FileInputStream和FileOutputStream实现文本文件的复制

过程

  1. 创建File类的对象,指明读入和写出的文件
  2. 创建输入流和输出流的对象
  3. 数据的读入和写入操作
  4. 关闭流资源
  5. try-catch-finally异常处理

代码实现

FileInputStream fis = null;
FileOutputStream fos = null;
try {
    File srcfile = new File("殷志源.png");
    File destfile = new File("丸子.png");

    fis = new FileInputStream(srcfile);
    fos = new FileOutputStream(destfile);

    byte[] buffer = new byte[5];
    int len;
    while((len = fis.read(buffer)) != -1){
        fos.write(buffer,0,len);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if(fis != null)
            fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        if(fos != null)
            fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

运行结果

oRznG.png
oRHMT.png

指定路径下文件的复制的方法

复制视频

public void copyFile(String srcPath, String destPath){
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
        File srcfile = new File(srcPath);
        File destfile = new File(destPath);

        fis = new FileInputStream(srcfile);
        fos = new FileOutputStream(destfile);

        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if(fis != null)
                fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            if(fos != null)
                fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ocIS1.png

od4o2.png

字节流和字符流使用的注意事项

  • 对于文本文件(.txt, .java, .c, .cpp......),使用字符流来处理
  • 对于非文本文件(.jpg, .mp3, .mp4, .avi, .doc, .ppt......),使用字节流来处理
  • 如果只是想复制文本文件,也可以使用字节流(流在此时只是个搬运的作用)
  • 非文本只可以用字节流操作
posted @ 2020-08-07 15:52  南煎丸子  阅读(256)  评论(0编辑  收藏  举报