java I/O流(一)——FileWriter,BufferedWriter,inputStream,BufferedInputStream,InputStreamReader

时间:2022-03-22 21:36:21

I/O全名:Input Output,输入输出的意思

•IO流用来处理设备之间的数据传输
•流操作分两种:字节流,字符流
•流按流向分为:输入流,输出流

java I/O流(一)——FileWriter,BufferedWriter,inputStream,BufferedInputStream,InputStreamReader

•字节流的抽象积累

◦InputStream
◦OutputStream

•字符流的抽象基类

◦Reader
◦Writer

FileWriter

•需求:在硬盘上创建一个文件,并且写入数据
那我们怎么去做?他构造函数比较多的,我们看例子

public class HelloJJAVA {
    public static void main(String[] args) {
        /** * 需求:在硬盘上创建一个文件,并且写入数据 */

        // 一被初始化就必须要有被操作的文件
        // 如果不指定位置,就创建在同目录下
        // 如果目录下存在同名文件,覆盖
        try {
            FileWriter fileWriter = new FileWriter("test.txt");
            // 写入数据到内存
            fileWriter.write("abcde");
            // 刷新该流的缓冲
            // fileWriter.flush();

            // 关闭流 关闭之前会刷新,和flush的区别在于flush刷新后流可以继续工作
            fileWriter.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这样在我们的项目根目录下就可以看到生成的文件了

文件续写
我们知道,文件存在的话就会覆盖,但是我们不想这样,我们想在原有的数据中续写,这该去怎么做?

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

        try {
            //参数2代表不覆盖已有的文件,支持续写
            FileWriter fileWriter = new FileWriter("demo.txt",true);
            fileWriter.write("你好");
            fileWriter.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

构造传参的时候设置为true就可以续写文件了

FileReader
既然写已经会了,那我们就来读取了

public class HelloJJAVA {
    public static void main(String[] args) {
        try {
            // 创建一个文件读取流对象,和指定名称的文件关联,保证文件存在,
            // 如果不存在,异常
            FileReader fileReader = new FileReader("demo.txt");
            // 读取单个字符,自动往下读
            int cd = fileReader.read();
            System.out.println((char) cd);

            //全部打印
            int ch = 0;
            while ((ch = fileReader.read()) != -1) {
                System.out.println(ch);
            }

            fileReader.close();

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这样就可以按照字节读取了,我们也可以把读到的字符存储在数组中

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

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

        try {
            FileReader fileReader = new FileReader("demo.txt");
            char[] buf = new char[3];

            int num = fileReader.read(buf);

            System.out.println("num:" + num + new String(buf));

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

文本复制
读写都说了,我们来看下其他的操作,我们首先来看复制

•复制原理:其实就是将C盘下的文件数据存储到D盘的一个文件中
实现的步骤:
1.在D盘创建一个文件,用于存储文件中的数据
2.定义读取流和文件关联
3.通过不断的读写完成数据的存储
关闭资源

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

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

        copy_1();
        copy_2();
    }

    // 从c盘读一个字符,就往D盘写一个字符
    public static void copy_1() {
        try {
            // 创建目的地
            FileWriter fw = new FileWriter("copy_1.txt");
            // 与已有文件关联
            FileReader fr = new FileReader("copy_1.txt");
            int ch = 0;
            while ((ch = fr.read()) != -1) {
                // 读一个 写一个
                fw.write(ch);
            }
            fw.close();
            fr.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void copy_2() {
        FileWriter fw = null;
        FileReader fr = null;

        try {
            fw = new FileWriter("copy_2.txt");
            fr = new FileReader("copy_2.txt");

            char[] buf = new char[1024];

            int len = 0;
            while ((len = fr.read(buf)) != -1) {
                fw.write(buf, 0, len);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }}

这里做了两种方式的拷贝方式,其实都是整理好思路,读和写的一个过程罢了!

字符流的缓冲区,提高了对数据的读写效率,他有两个子类
•BufferedWriter
•BufferedReader

我们还是复制文件这个问题,现在我们有缓冲区,我们要怎么样复制文件?


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class HelloJJAVA {
    public static void main(String[] args) {
        /** * 缓冲区文件复制 */
        BufferedReader bufr = null;
        BufferedWriter bufw = null;

        try {
            bufr = new BufferedReader(new FileReader("buffer.txt"));
            bufw = new BufferedWriter(new FileWriter("buffercopy.txt"));

            String line = null;

            while((line = bufr.readLine()) != null){
                bufw.write(line);
            }

            //关闭流
            bufr.close();
            bufw.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

字节流读取操作
字符流我们讲的差不多了,我们接着说字节,其实他们类似的,知识他操作的是字节而已

•inputStream:读
•outputStream:写
我们还是从例子开始

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

public class HelloJJAVA {
    public static void main(String[] args) {
        writeFile();

    }

    // 写文件
    public static void writeFile() {
        try {
            FileOutputStream fo = new FileOutputStream("demo.txt");
            fo.write("test".getBytes());
            fo.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

专门处理的字节流

public static void readFile2() {
        try {
            FileInputStream fs = new FileInputStream("demo.txt");
            int num = fs.available();
            System.out.println(num);
            fs.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

我们发现直接用available就可以拿到字节了,原理其实是这段代码

public static void readFile2() {
        try {
            FileInputStream fs = new FileInputStream("demo.txt");
            byte[] buf = new byte[fs.available()];
            fs.read(buf);
            System.out.println(new String(buf));
            fs.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

字节流的缓冲区

这个,和我们的字符流基本上没有什么差别,我们来拷贝mp3,看例子

// 通过字节流的缓冲区拷贝图片
    public static void copyMp3() {

        try {
            FileInputStream fi = new FileInputStream("audio.mp3");
            BufferedInputStream buf = new BufferedInputStream(fi);

            FileOutputStream fio = new FileOutputStream("audioCapy.mp3");
            BufferedOutputStream buo = new BufferedOutputStream(fio);

            int ch = 0;

            while ((ch = buf.read()) != -1) {
                buo.write(ch);
            }

            buf.close();
            buo.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
//这样,就直接拷贝了

转换流InputStreamReader

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class HelloJJAVA {
    public static void main(String[] args) throws IOException {
        //获取键盘录入对象
        InputStream in = System.in;
        //转换
        InputStreamReader isr = new InputStreamReader(in);
        //提高效率
        BufferedReader bur = new BufferedReader(isr);
        String line = null;
        while((line = bur.readLine()) != null){
            if(line.equals("over"))
                break;
            System.out.println(line.toString());
        }
    }
}

写入转换流

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

public class HelloJJAVA {
    public static void main(String[] args) throws IOException {
        //获取键盘录入对象
        InputStream in = System.in;
        //转换
        InputStreamReader isr = new InputStreamReader(in);
        //提高效率
        BufferedReader bur = new BufferedReader(isr);

        OutputStream os = System.out;
        OutputStreamWriter osw = new OutputStreamWriter(os);
        BufferedWriter bufw = new BufferedWriter(osw);


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

如何选择流?
◦1.明确源和目的

■源:输入流 InputStream Reader
■目的:输出流 OutputStream writer
◦2.明确操作的数据是否是纯文本

■是:字符流
■不是:字节流