文件与IO流基础接收(全面)

文件与IO流

文章目录

  • 文件与IO流
      • 1. 文件
      • 2. 常用的文件操作
      • 3. 常用的流操作
        • 3.1 流的分类
        • 3.2 FileInputStream 介绍
        • 3.3 FileOutputStream的介绍
        • 3.4 FileReader 与 FileWriter
        • 3.5 处理流 BufferReader和BufferWriter介绍
        • 3.6 处理流 BufferedOutputStream 和 BufferedInputStream

1. 文件

  1. 定义:文件是保存数据的地方
  2. 文件流:流,顾名思义,是一个流动的东西,也可以说是一个路径。表达的是从文件到程序(内存)之间的路径,输入与输出(In or Out)是相对于程序来说的。
    2.1 输入流:从文件(外存)到程序(内存)之间的路径
    2.2 输出流:从程序(内存)到文件(外存)之间的路径
    文件与IO流基础接收(全面)_第1张图片

2. 常用的文件操作

  1. File的构造
    1.1 根据路径构造一个File文件。new File(String pathname)
    1.2 根据父目录文件+子路径构造。new File(File parent, String Child)
    1.3 根据父目录+子路径构造。new File(String parent, String Child)
    1.4 注意:new File(…)的时候并没有真正的创建文件,只有执行了createFile方法的时候,才在磁盘创建了该文件。
    给出一个例子:
    //方式2 new File(File parent,String child) //根据父目录文件+子路径构建
    //e:\\news2.txt
    @Test
    public  void create02() {
        File parentFile = new File("e:\\");
        String fileName = "news2.txt";
        //这里的file对象,在java程序中,只是一个对象
        //只有执行了createNewFile 方法,才会真正的,在磁盘创建该文件
        File file = new File(parentFile, fileName);

        try {
            file.createNewFile();
            System.out.println("创建成功~");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  1. 获取文件相关信息
    这里就是简单的方法调用,File对象是调用的主体。
    文件与IO流基础接收(全面)_第2张图片
  2. 目录操作
    3.1 目录也是一种特殊的文件,可以使用exists方法来判断是否存在
    3.2 创建目录有两个方法,分别是创建创建一级目录的:mkdir();创建多级目录的:mkdirs()
    下面给出一个示例:
    //判断 D:\\demo\\a\\b\\c 目录是否存在,如果存在就提示已经存在,否则就创建
    @Test
    public void m3() {

        String directoryPath = "D:\\demo\\a\\b\\c";
        File file = new File(directoryPath);
        if (file.exists()) {
            System.out.println(directoryPath + "存在..");
        } else {
            if (file.mkdirs()) { //创建一级目录使用mkdir() ,创建多级目录使用mkdirs()
                System.out.println(directoryPath + "创建成功..");
            } else {
                System.out.println(directoryPath + "创建失败...");
            }
        }

3. 常用的流操作

  1. I/O技术是Input/Output的缩写,是非常使用的技术,用于数据处理,读写文件,网络通讯等等。
  2. 数据的输入/输出操作以“流(stream)”的方式进行。
  3. java.io包中,提供了各种“流”的类和接口,用于获取不同的种类的数据,通过方法输入或者输出数据。
3.1 流的分类
  1. 根据数据方向的不同:输入流 与 输出流
  2. 根据读取/写入的单位的不同:字节流 与 字符流
  3. 根据功能的不同:节点流 与 处理流
  4. 四个抽象基类,派生出40多个类,派生出的子类的名称以其父类名作为子类名后缀。
    文件与IO流基础接收(全面)_第3张图片文件与IO流基础接收(全面)_第4张图片
3.2 FileInputStream 介绍

FileInputStream的继承关系:
文件与IO流基础接收(全面)_第5张图片
既然是从文件中按照字节的方式读取到内存中的类,那么这个类中最重要的方法一定是read,下面给出一个使用字节数组读取数据的示例

/**
     * 使用 read(byte[] b) 读取文件,提高效率
     */
    @Test
    public void readFile02() {
        String filePath = "e:\\hello.txt";
        //字节数组
        byte[] buf = new byte[8]; //一次读取8个字节.
        int readLen = 0;
        FileInputStream fileInputStream = null;
        try {
            //创建 FileInputStream 对象,用于读取 文件
            fileInputStream = new FileInputStream(filePath);
            //从该输入流读取最多b.length字节的数据到字节数组。 此方法将阻塞,直到某些输入可用。
            //如果返回-1 , 表示读取完毕
            //如果读取正常, 返回实际读取的字节数
            while ((readLen = fileInputStream.read(buf)) != -1) {
                System.out.print(new String(buf, 0, readLen));//显示
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭文件流,释放资源.
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
3.3 FileOutputStream的介绍

继承关系:
文件与IO流基础接收(全面)_第6张图片
既然是从内存向文件输出信息,那么最重要的方法是write()。给出使用的示例:

    @Test
    public void writeFile() {

        //创建 FileOutputStream对象
        String filePath = "e:\\a.txt";
        FileOutputStream fileOutputStream = null;
        try {
            //得到 FileOutputStream对象 对象
            //老师说明
            //1. new FileOutputStream(filePath) 创建方式,当写入内容是,会覆盖原来的内容
            //2. new FileOutputStream(filePath, true) 创建方式,当写入内容是,是追加到文件后面
            fileOutputStream = new FileOutputStream(filePath, true);
            //写入一个字节
            //fileOutputStream.write('H');//
            //写入字符串
            String str = "hsp,world!";
            //str.getBytes() 可以把 字符串-> 字节数组
            //fileOutputStream.write(str.getBytes());
            /*
            write(byte[] b, int off, int len) 将 len字节从位于偏移量 off的指定字节数组写入此文件输出流
             */
            fileOutputStream.write(str.getBytes(), 0, 3);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
3.4 FileReader 与 FileWriter
  • 3.2 与 3.3 介绍的两个类,是按照字节读取文件适用于视频或者音频等。
    而现在介绍的这两个类使用字符来读取文件,适用于文本文件,不适用于二进制文件,如果用他们来读取二进制文件会出现乱码。
  • 下面介绍一下两者的不同
    • 处理速度:

      • 字节流在处理大量数据时具有较高的速度和效率,因为它直接操作字节,无需进行字符解码或编码。
      • 字符流在处理文本数据时的速度可能较慢,因为它需要先转换成字符,然后才能进行后续的操作。
    • 数据表现形式:

      • 字节流以字节的形式读取和写入数据,可以处理所有类型的数据,包括图像、音频和视频等。
      • 字符流以字符的形式读取和写入数据,通常只处理文本数据。
        文件与IO流基础接收(全面)_第7张图片
    /**
     * 字符数组读取文件
     */
    @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();
            }
        }
    }
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 {
            try {
                //fileWriter.flush();
                //关闭文件流,等价 flush() + 关闭
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

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


    }
}
3.5 处理流 BufferReader和BufferWriter介绍

文件与IO流基础接收(全面)_第8张图片
文件与IO流基础接收(全面)_第9张图片
让我们来看看BufferReader和BuffWriter的源代码
文件与IO流基础接收(全面)_第10张图片
文件与IO流基础接收(全面)_第11张图片
也就是说,BuffReader中封装了一个reader和一个字符数组,这样的话提高了读的效率
下面给出一个例子

public class BufferedReader_ {
    public static void main(String[] args) throws Exception {

        String filePath = "e:\\a.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.close();

    }
}
    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("hello2, 韩顺平教育!");
        bufferedWriter.newLine();
        bufferedWriter.write("hello3, 韩顺平教育!");
        bufferedWriter.newLine();

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

    }
}

3.6 处理流 BufferedOutputStream 和 BufferedInputStream

与3.5类似,这两分别是OutputStream和InputStream的包装流
给出示例

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

//        String srcFilePath = "e:\\Koala.jpg";
//        String destFilePath = "e:\\hsp.jpg";
//        String srcFilePath = "e:\\0245_韩顺平零基础学Java_引出this.avi";
//        String destFilePath = "e:\\hsp.avi";
        String srcFilePath = "e:\\a.java";
        String destFilePath = "e:\\a3.java";

        //创建BufferedOutputStream对象BufferedInputStream对象
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            //因为 FileInputStream  是 InputStream 子类
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));

            //循环的读取文件,并写入到 destFilePath
            byte[] buff = new byte[1024];
            int readLen = 0;
            //当返回 -1 时,就表示文件读取完毕
            while ((readLen = bis.read(buff)) != -1) {
                bos.write(buff, 0, readLen);
            }

            System.out.println("文件拷贝完毕~~~");

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

            //关闭流 , 关闭外层的处理流即可,底层会去关闭节点流
            try {
                if(bis != null) {
                    bis.close();
                }
                if(bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


    }
}

以上内容来自 韩顺平学java

你可能感兴趣的:(java)