IO流的讲解(2)

目录

文件拷贝

FileReader

FileWriter

节点流和处理流

基本介绍

节点流和处理流的区别

处理流-BufferedReader和BufferedWriter

案例1

案例2

案例3


对于文件的拷贝,对于我们日常的使用来说,也就是复制粘贴的事情,但是我们如何在Java程序中实现呢

文件拷贝

代码演示:

首先我们要定义好几个熟悉,分别是文件的输入流和输出流,然后要定好,要拷贝那一个文件的路径,然后指定要拷贝到那一个目录下去

然后我们先使用文件输入流,先读取文件,在读取的过程中,我们直接写入,这样当fileInputStream.read(buf)这个方法的返回值是-1的时候,表示读取完毕了,此事文件也写入完毕了

注意,读取和写入完毕之后,要关闭对应的输入流和输出流

package com.outputstream_;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopy {
    public static void main(String[] args) {
        //完成 文件拷贝,将 e:\\Koala.jpg 拷贝 c:\\
        //思路分析
        //1. 创建文件的输入流 , 将文件读入到程序
        //2. 创建文件的输出流, 将读取到的文件数据,写入到指定的文件.
        String srcFilePath = "e:\\123.jpg";
        String destFilePath = "d:\\123.jpg";
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;

        try {

            fileInputStream = new FileInputStream(srcFilePath);
            fileOutputStream = new FileOutputStream(destFilePath);
            //定义一个字节数组,提高读取效果
            byte[] buf = new byte[1024];
            int readLen = 0;
            while ((readLen = fileInputStream.read(buf)) != -1) {
                //读取到后,就写入到文件 通过 fileOutputStream
                //即,是一边读,一边写
                fileOutputStream.write(buf, 0, readLen);//一定要使用这个方法

            }
            System.out.println("拷贝ok~");


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭输入流和输出流,释放资源
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
}

FileReader

FileReader基本介绍

FileReader类用于读取字符文件,可以读取一个字符、一行或整个文件。 它的构造函数接受一个文件名或文件对象作为参数,并打开该文件以供读取。读取时,可以使用read()方法读取单个字符,或者使用readLine()方法读取一个字符串并自动跳过行末换行符。

FileReader相关方法:

1.new FileReader(File/String)

2.read:每次读取单个字符,返回该字符,如果到文件未尾返回-1

3.read(char[]): 批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1

相关API:

1.new String(char[]):将char[]转换成String

2.new String(char[],off,len):将char[]]的指定部分转换成String

代码演示:

package com.reader_;

import org.junit.jupiter.api.Test;

import java.io.FileReader;
import java.io.IOException;

public class FileReader_ {
    public static void main(String[] args) {


    }

    /**
     * 单个字符读取文件
     */
    @Test
    public void readFile01() {
        String filePath = "e:\\story.txt";
        FileReader fileReader = null;
        int data = 0;
        //1. 创建FileReader对象
        try {
            fileReader = new FileReader(filePath);
            //循环读取 使用read, 单个字符读取
            while ((data = fileReader.read()) != -1) {
                System.out.print((char) data);
            }

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

    /**
     * 字符数组读取文件
     */
    @Test
    public void readFile02() {
        System.out.println("~~~readFile02 ~~~");
        String filePath = "e:\\story.txt";
        FileReader fileReader = null;

        int readLen = 0;
        char[] buf = new char[8];
        //1. 创建FileReader对象
        try {
            fileReader = new FileReader(filePath);
            //循环读取 使用read(buf), 返回的是实际读取到的字符数
            //如果返回-1, 说明到文件结束
            while ((readLen = fileReader.read(buf)) != -1) {
                System.out.print(new String(buf, 0, readLen));
            }

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

}

FileWriter

FileWriter基本介绍

FileWriter类用于写入字符文件。与FileReader类似,它的构造函数接受一个文件名或文件对象作为参数,并打开该文件以供写入。写入时,可以使用write()方法写入单个字符,或者使用write(String)方法写入一个字符串。最后必须调用close()方法关闭文件或使用try-with-resources语句自动关闭文件。

FileWriter常用方法

1.new FileWriter(File/String): 覆盖模式,相当于流的指针在首端

2.new FileWriter(File/String,true): 追加模式,相当于流的指针在尾端

3.write(int):写入单个字符

4.write(char[]):写入指定数组

5.write(char[],off,len):写入指定数组的指定部分

6.write (string): 写入整个字符串

7.write(string,offlen):写入字符串的指定部分

相关API: String类: toCharArray:将String转换成char[]

注意:

FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!

代码演示:

这里需要注意的是 //关闭文件流,等价 flush() + 关闭

package com.writer_;

import java.io.FileWriter;
import java.io.IOException;

public class FileWriter_ {
    public static void main(String[] args) {

        String filePath = "e:\\note.txt";
        //创建FileWriter对象
        FileWriter fileWriter = null;
        char[] chars = {'a', 'b', 'c'};
        try {
            fileWriter = new FileWriter(filePath);//默认是覆盖写入
//            3) write(int):写入单个字符
            fileWriter.write('H');
//            4) write(char[]):写入指定数组
            fileWriter.write(chars);
//            5) write(char[],off,len):写入指定数组的指定部分
            fileWriter.write("韩顺平教育".toCharArray(), 0, 3);
//            6) write(string):写入整个字符串
            fileWriter.write(" 你好北京~");
            fileWriter.write("风雨之后,定见彩虹");
//            7) write(string,off,len):写入字符串的指定部分
            fileWriter.write("上海天津", 0, 2);
            //在数据量大的情况下,可以使用循环操作.


        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            //对应FileWriter , 一定要关闭流,或者flush才能真正的把数据写入到文件
            //看源码就知道原因.
            /*

                private void writeBytes() throws IOException {
        this.bb.flip();
        int var1 = this.bb.limit();
        int var2 = this.bb.position();

        assert var2 <= var1;

        int var3 = var2 <= var1 ? var1 - var2 : 0;
        if (var3 > 0) {
            if (this.ch != null) {
                assert this.ch.write(this.bb) == var3 : var3;
            } else {
                this.out.write(this.bb.array(), this.bb.arrayOffset() + var2, var3);
            }
        }

        this.bb.clear();
    }
             */
            try {
                //fileWriter.flush();
                //关闭文件流,等价 flush() + 关闭
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        System.out.println("程序结束...");


    }
}

节点流和处理流

基本介绍

1.节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter [源码]

2.处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter [源码]

节点流和处理流的区别

节点流和处理流的区别和联系

1.节点流是底层流/低级流,直接跟数据源相接

2.处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。[源码理解]

3.处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连[模拟修饰器设计模式]

处理流的功能主要体现在以下两个方面:

1.性能的提高:主要以增加缓冲的方式来提高输入输出的效率

2.操作的便捷: 处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

代码演示:

package com;

public class Test_ {
    public static void main(String[] args) {


        BufferedReader_ bufferedReader_ = new BufferedReader_(new FileReader_());
        bufferedReader_.readFiles(10);
        //bufferedReader_.readFile();
        //Serializable
        //Externalizable
        //ObjectInputStream
        //ObjectOutputStream
        //这次希望通过 BufferedReader_ 多次读取字符串
        BufferedReader_ bufferedReader_2 = new BufferedReader_(new StringReader_());
        bufferedReader_2.readStrings(5);
    }
}


package com;

/**
 * 节点流
 */
public class StringReader_ extends Reader_{
    public void readString() {
        System.out.println("读取字符串");
    }
}


package com;

/**
 * 节点流
 */
public class FileReader_ extends Reader_{
     public void readFile(){
         System.out.println("读取文件");
     }
}


package com;

/**
 * 做成处理流/包装流
 */
public class BufferedReader_ extends Reader_{

    private Reader_ reader_; //属性是 Reader_类型

    //接收Reader_ 子类对象
    public BufferedReader_(Reader_ reader_) {
        this.reader_ = reader_;
    }

    public void readFile() { //封装一层
        reader_.readFile();
    }

    //让方法更加灵活, 多次读取文件, 或者加缓冲byte[] ....
    public void readFiles(int num) {
        for(int i = 0; i < num; i++) {
            reader_.readFile();
        }
    }

    //扩展 readString, 批量处理字符串数据
    public void readStrings(int num) {
        for(int i = 0; i <num; i++) {
            reader_.readString();
        }
    }

}


package com;

public abstract class Reader_ {
    public void readString() {
    }

    public void readFile() {
    }
}

处理流-BufferedReader和BufferedWriter

BufferedReader类基本介绍

BufferedReader类用来读取字符流,通过将读取的字符缓存到内存中,减少了I/O操作的次数,提高了读取数据的效率。BufferedReader类中提供了read()、readLine()等方法用来读取字符流,同时也提供了mark()、reset()等方法来支持流的标记和重置。

BufferedReader 和 BufferedWriter 属于字符流是按照字符来读取数据的

关闭时处理流,只需要关闭外层流即可[后面看源码]

案例1

代码演示:

这里要注意的是bufferedReader.readLine())该方法,当把文件读取完毕的时候,会返回null

package com.reader_;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 * 演示bufferedReader 使用
 */
public class BufferedReader_ {
    public static void main(String[] args) throws Exception {

        String filePath = "e:\\asd.java";
        //创建bufferedReader
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        //读取
        String line; //按行读取, 效率高
        //说明
        //1. bufferedReader.readLine() 是按行读取文件
        //2. 当返回null 时,表示文件读取完毕
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }

        //关闭流, 这里注意,只需要关闭 BufferedReader ,因为底层会自动的去关闭 节点流
        //FileReader。
        /*
            public void close() throws IOException {
                synchronized (lock) {
                    if (in == null)
                        return;
                    try {
                        in.close();//in 就是我们传入的 new FileReader(filePath), 关闭了.
                    } finally {
                        in = null;
                        cb = null;
                    }
                }
            }

         */
        bufferedReader.close();

    }
}

案例2

BufferedWriter类基本介绍

BufferedWriter类用来写入字符流,通过将写入的字符缓存到内存中,减少了I/O操作的次数,提高了写入数据的效率。BufferedWriter类中提供了write()、newLine()等方法用来写入字符流,同时也提供了flush()方法来将缓冲区的内容写入到文件中。

代码演示:

        说明:关闭外层流即可 , 传入的 new FileWriter(filePath) ,会在底层关闭
 

package com.writer_;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 演示BufferedWriter的使用
 */
public class BufferedWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath = "e:\\ok.txt";
        //创建BufferedWriter
        //说明:
        //1. new FileWriter(filePath, true) 表示以追加的方式写入
        //2. new FileWriter(filePath) , 表示以覆盖的方式写入
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
        bufferedWriter.write("hello, 你好!");
        bufferedWriter.newLine();//插入一个和系统相关的换行
        bufferedWriter.write("hello, 你好!");
        bufferedWriter.newLine();
        bufferedWriter.write("hello, 你好!");
        bufferedWriter.newLine();

        //说明:关闭外层流即可 , 传入的 new FileWriter(filePath) ,会在底层关闭
        bufferedWriter.close();

    }
}

案例3

代码演示:

和之前的拷贝文件一样,指定要读取的文件的路径,在指定一个,拷贝到哪里的路径,然后使用while循环读取,一边读取一边写入,当bufferedReader.readLine())等于null时,说明文件已经读取完毕,同时也写入完毕,最后关闭对应的流即可

package com.writer_;

import com.BufferedReader_;

import java.io.*;

public class BufferedCopy_ {
    public static void main(String[] args) {

        //说明
        //1. BufferedReader 和 BufferedWriter 是按照字符操作
        //2. 不要去操作 二进制文件[声音,视频,doc, pdf ], 可能造成文件损坏
        //应该使用 BufferedInputStream 和 BufferedOutputStream因为他们是按字节操作
        
        String scr = "e:\\asd.java";
        String dest = "e:a2.java";

        BufferedWriter bufferedWriter = null;
        BufferedReader bufferedReader = null;

        String line;
        try {
            bufferedReader = new BufferedReader(new FileReader(scr));
            bufferedWriter = new BufferedWriter((new FileWriter(dest)));

            //说明: readLine 读取一行内容,但是没有换行
            while ((line = bufferedReader.readLine()) != null) {
                //每读取一行,就写入
                bufferedWriter.write(line);
                //插入一个换行
                bufferedWriter.newLine();
            }
            System.out.println("拷贝成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //关闭流
            try {
                if (bufferedWriter != null) {
                    bufferedWriter.close();
                }
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值