十六、IO流

一、文件

1.1 文件简介

在这里插入图片描述

1.2 文件流

在 Java API 中,可以从其中读入一个字节(字符)序列的对象称作输入流,而可以向其中写入一个字节(字符)序列的对象称作输出流。这些字节序列的来源地和目的地可以是文件,而通常都是文件,但是也可以是网络连接,甚至是内存块
摘自:Java核心技术卷

在这里插入图片描述

1.3 常用的文件操作

1.3.1 创建文件

在这里插入图片描述

在这里插入图片描述

package com.gyh.io;

import java.io.File;
import java.io.IOException;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class FileCreate {
    public static void main(String[] args) {
//        create01();
//        create02();
        create03();
    }

    // 方式一: new File(String pathname)
    public static void create01() {
        String filePath = "E:\\idea_java_projects\\io\\e.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 方式二:new File(File parent,String child)
    public static void create02() {
        File fFile = new File("E:\\idea_java_projects\\io");
        // 这里的file对象,在java程序中,只是一个对象
        // 只有执行了createNewFile 方法,才会真正的在磁盘创建该文件
        File file = new File(fFile, "e2.txt");
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 方式二:new File(String parent,String child)
    public static void create03() {
        // 这里的file对象,在java程序中,只是一个对象
        // 只有执行了createNewFile 方法,才会真正的在磁盘创建该文件
        File file = new File("E:\\idea_java_projects\\io", "e3.txt");
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

1.3.2 获取文件的相关信息

在这里插入图片描述

package com.gyh.io;

import java.io.File;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class FileInformation {
    public static void main(String[] args) {
        info();
    }

    // 获取文件的信息
    public static void info() {
        // 先创建文件对象
        File file = new File("E:\\idea_java_projects\\io\\e.txt");
        // 调用相应的方法,得到对应的信息
        System.out.println("文件的名字:" + file.getName());
        System.out.println("文件的绝对路径:" + file.getAbsolutePath());
        System.out.println("文件的父级目录:" + file.getParent());
        System.out.println("文件的大小(字节)=" + file.length());// 一个英文字母1个字节,一个汉字3个字节
        System.out.println("文件是否存在" + file.exists());
        System.out.println("是不是文件类型:" + file.isFile());
        System.out.println("是不是目录(文件夹)类型:" + file.isDirectory());
    }
}

1.3.3 目录的操作和文件删除

在这里插入图片描述

package com.gyh.io;

import java.io.File;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Directory_ {
    public static void main(String[] args) {
//        m1();
//        m2();
        m3();
    }

    // 判断 E:\idea_java_projects\e.txt 是否存在,如果存在就删除
    public static void m1() {
        String filePath = "E:\\idea_java_projects\\io\\e.txt";
        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("删除成功!");
            } else {
                System.out.println("删除失败");
            }
        } else {
            System.out.println("该文件不存在!");
        }
    }

    // 判断 E:\idea_java_projects\io\demo_dir 是否存在,存在就删除,否则提示不存在
    // 这里我们需要体会到,在 java 编程中,目录也被当做文件
    public static void m2() {
        String filePath = "E:\\idea_java_projects\\io\\demo_dir";
        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("删除成功!");
            } else {
                System.out.println("删除失败");
            }
        } else {
            System.out.println("该文件夹不存在!");
        }
    }

    // 判断 E:\idea_java_projects\io\demo_dir\sub_demo_dir1 是否存在,
    // 如果存在就提示已经存在,否则就创建
    public static void m3() {
        String filePath = "E:\\idea_java_projects\\io\\demo_dir\\sub_demo_dir";
        File file = new File(filePath);
        if (!file.exists()) {
            if (file.mkdirs()) { // 创建多级目录
                System.out.println("该目录创建成功");
            } else {
                System.out.println("该目录创建失败");
            }
        } else {
            System.out.println("该目录已经存在");
        }
    }

}

二、Io流原理及流的分类

2.1 Java IO流原理

在 Java API 中,可以从其中读入一个字节(字符)序列的对象称作输入流,而可以向其中写入一个字节(字符)序列的对象称作输出流。这些字节序列的来源地和目的地可以是文件,而通常都是文件,但是也可以是网络连接,甚至是内存块
摘自:Java核心技术卷

在这里插入图片描述

在这里插入图片描述

2.2 流的分类

在这里插入图片描述

在这里插入图片描述

  • 在java中是处理数据传输的对象

三、FileInputStream 和 FileoutputStream

在这里插入图片描述

在这里插入图片描述

3.1 FileInputStream

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.gyh.io;

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

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class FileInputStream_ {
    public static void main(String[] args) {
//        readFile01();
        readFile02();

    }

    /**
     * 单个字节的读取,效率比较低
     * -> 使用 read(byte[] b)
     */
    public static void readFile01() {
        String filePath = "E:\\idea_java_projects\\io\\e2.txt";
        int content = 0;
        FileInputStream fileInputStream = null;
        try {
            // 创建 FileInputStream 对象,用于读取 文件
            fileInputStream = new FileInputStream(filePath);
            // 从该输入流读取一个字节的数据。如果没有输入可用,此方法将阻止。
            // 如果返回一个-1,表示读取完毕
            while ((content = fileInputStream.read()) != -1) {
                System.out.println((char) content);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭文件流,释放资源
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 使用 read(byte []) 方法
     */
    public static void readFile02() {
        String filePath = "E:\\idea_java_projects\\io\\e2.txt";
        int content = 0;
        // 定义字节数组
        byte[] buf = new byte[8]; // 一次读取8个字节
        // 实际上读取的个数
        int actReadLen = 0;
        FileInputStream fileInputStream = null;
        try {
            // 创建 FileInputStream 对象,用于读取 文件
            fileInputStream = new FileInputStream(filePath);
            // 从该输入流读取一个字节的数据。如果没有输入可用,此方法将阻止。
            // 如果读取正常,返回实际读取的字节数
            // 如果返回一个-1,表示读取完毕
            while ((actReadLen = fileInputStream.read(buf)) != -1) {
                System.out.println(new String(buf, 0, actReadLen));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭文件流,释放资源
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.2 FileoutputStream

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.gyh.io;

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

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class FileOutputStream_ {
    public static void main(String[] args) {
        writeFile01();
    }

    /**
     * 演示使用 FileOutputStream 将数据到文件中,
     * 如果该文件不存在,则创建该文件
     */
    public static void writeFile01() {
        // 创建 FileOutputStream 对象
        String filePath = "E:\\idea_java_projects\\io\\e3.txt";
        FileOutputStream fileOutputStream = null;
        try {
            // 说明:
            // 1. new FileOutputStream(filePath) 创建方式,当写入内容时,会覆盖原来的内容
            // 2. new FileOutputStream(filePath,true) 创建方式,当写入内容时,是追加到文件后面
            // 得到 fileOutputStream 对象
            fileOutputStream = new FileOutputStream(filePath);
            // 写入一个字节
//            fileOutputStream.write('a'); // chat 自动-> byte
            String str = "hello,world";
//            str.getBytes() 可以把 字符串 -> 字节数组
            fileOutputStream.write(str.getBytes());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.3 文件拷贝

在这里插入图片描述

package com.gyh.io;

import java.io.*;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class FileCopy {
    public static void main(String[] args) {
        cpy();
    }

    public static void cpy() {
        String originPath = "C:\\Users\\Gaoyonghao\\Desktop\\1.PNG";
        String disPath = "E:\\idea_java_projects\\io\\1.PNG";
        // 创建 FileInputStream
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        int readLen; // 获取真实的字节个数
        try {
            fileInputStream = new FileInputStream(originPath);
            // 创建新的文件
            File file = new File(disPath);
//            if (!file.exists()) file.createNewFile();
            fileOutputStream = new FileOutputStream(file);
            // 设置一次读取多少字节
            byte[] buf = new byte[1024];
            while ((readLen = fileInputStream.read(buf)) != -1) {
                fileOutputStream.write(buf, 0, readLen);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流资源
            try {
                if (fileInputStream != null) fileInputStream.close();
                if (fileOutputStream != null) fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
}

四、FileReader 和 FileWriter

在这里插入图片描述

在这里插入图片描述

4.1 FileReader

在这里插入图片描述

package com.gyh.io;


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

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class FileReader_ {
    public static void main(String[] args) {
        read01();
    }

    public static void read01() {
        String filePath = "E:\\idea_java_projects\\io\\e3.txt";
        FileReader fileReader = null;
        int data = 0;
        try {
            fileReader = new FileReader(filePath);
            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();
            }
        }
    }

    public static void read02() {
        String filePath = "E:\\idea_java_projects\\io\\e3.txt";
        FileReader fileReader = null;
        char[] chars = new char[5];
        int readLen = 0; // 实际每一次得到的字符数
        try {
            fileReader = new FileReader(filePath);
            while ((readLen = fileReader.read(chars)) != -1) {
                System.out.print(new String(chars, 0, readLen));
            }

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

                    fileReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4.2 FileWriter

在这里插入图片描述

package com.gyh.io;

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

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class FileWriter_ {
    public static void main(String[] args) {
        writer();
    }

    private static void writer() {
        String filePath = "E:\\idea_java_projects\\io\\note.txt";
        FileWriter fileWriter = null;
        String content = "风雨之后,定见彩虹";
        try {
            fileWriter = new FileWriter(filePath);
            // 写入单个字符
//            fileWriter.write('H');
            // 写入指定数组
//            fileWriter.write(content.toCharArray());
            // 写入整个字符串
//            fileWriter.write(content);
            // 写入字符串指定部分
            fileWriter.write(content, 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 {
                // flush方法作用是 刷新该流的缓冲,如果没有执行,内容不会写入到文件中
//                fileWriter.flush();
                // 关闭文件流等价于 flush() + 关闭
                if (fileWriter != null) fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

五、节点流和处理流

5.1 基本介绍

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

// 模拟修饰器设计模式
package com.gyh.io;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public abstract class Reader_ { // 抽闲类
    public abstract void read();
}

class BufferedReader_ extends Reader_ {
    private Reader_ r; // 属性时 Reader_ 类型

    public BufferedReader_(Reader_ r) {
        this.r = r;
    }

    // 让方法更加灵活,多次读取文件
    public void readerFiles(int num) {
        for (int i = 0; i < num; i++) {
            r.read();
        }
    }

    @Override
    public void read() { // 封装一层
        r.read();
    }
}

/**
 * 可以认为是节点流
 */
class FileReader01 extends Reader_ {
    public void read() {
        System.out.println("对文件进行读取");
    }
}

/**
 * 可以认为是节点流
 */
class StringReader01 extends Reader_ {
    public void read() {
        System.out.println("对字符串进行读取");
    }
}

六、BufferedInputStream 和 BufferedOutputStream

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

七、BufferedReader 和 BufferedWriter

7.1 BufferedReader

在这里插入图片描述

在这里插入图片描述

package com.gyh.io;

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

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class BufferedReader01 {
    public static void main(String[] args) {
        read();
    }

    public static void read() {
        // 创建缓冲流对象,套接在指定的结点流基础上
        String dataPath = "E:\\idea_java_projects\\io\\e2.txt";
        BufferedReader bufferedReader = null;
        String line;
        try {
            bufferedReader = new BufferedReader(new FileReader(dataPath));
            // 1. line = bufferedReader.readLine() 是按行读取文件
            // 2. 当返回 null 时,表示文件读取完毕
            while ((line = bufferedReader.readLine()) != null) { // 按行读取效率高
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流,这里注意,只需要关闭 BufferedReader, 因为底层会自动的去关闭 节点流
            if (bufferedReader != null) {
                try {
                    // 源码
                    /*
                    * public void close() throws IOException {
                            synchronized (lock) {
                                if (in == null)
                                    return;
                                try {
                                    in.close();
                                } finally {
                                    in = null;
                                    cb = null;
                                }
                            }
                        }
                    *
                    * */
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

7.2 BufferedWriter

在这里插入图片描述

package com.gyh.io;

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

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class BufferedWriter_ {
    public static void main(String[] args) {
        write();
    }

    public static void write() {
        String dataPath = "E:\\idea_java_projects\\io\\e3.txt";
        BufferedWriter bufferedWriter = null;
        try {
            // 说明:
            // 1. new FileWriter(dataPath, true) 表示以追加的方式写入
            // 2. new FileWriter(dataPath, false) 或 new FileWriter(dataPath) 表示以覆盖的方式写入
            bufferedWriter = new BufferedWriter(new FileWriter(dataPath, true));
            bufferedWriter.write("hello,韩顺平教育");
            bufferedWriter.newLine(); // 插入一个和系统相关的换行符
            bufferedWriter.write("hello,韩顺平教育");
            bufferedWriter.newLine(); // 插入一个和系统相关的换行符
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 说明:关闭外层流即可,传入的new FileWriter(filePath),会在底层关闭
            if (bufferedWriter != null) {
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

7.3 BufferedReader与BufferedWriter应用案例

在这里插入图片描述

package com.gyh.io;

import java.io.*;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class BufferedCopy {
    public static void main(String[] args) {
        copy();
    }

    /**
     * 说明:
     * 1. BufferedReader 和 BufferedWriter 是处理字符的
     * 2. 不要去操作 二进制文件[声音,时频,等]
     */
    public static void copy() {
        String originDataPath = "E:\\idea_java_projects\\io\\e2.txt";
        String disDataPath = "E:\\idea_java_projects\\io\\note.txt";
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        String line;
        try {
            bufferedReader = new BufferedReader(new FileReader(originDataPath));
            bufferedWriter = new BufferedWriter(new FileWriter(disDataPath));
            while ((line = bufferedReader.readLine()) != null) {
                bufferedWriter.write(line);
                bufferedWriter.newLine();// 换行
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null) bufferedReader.close();
                if (bufferedWriter != null) bufferedWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

八、对象流-ObjectInputStream 和 ObejctOutputStream

8.1 基本介绍

在这里插入图片描述

在这里插入图片描述

8.2 应用案例

在这里插入图片描述

package com.gyh.io;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class ObjectOutStream01 {
    public static void main(String[] args) {
        // 序列化后保存的文件格式不是纯文本,而是按照它的格式来保存
        String filePath = "E:\\idea_java_projects\\io\\data.dat";
        ObjectOutputStream objectOutputStream = null;
        try {
            objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
            objectOutputStream.writeInt(100); // int -> Integer(实现了 Serializable)
            objectOutputStream.writeUTF("韩顺平教育");
            // 保存一个Demo对象(序列化)
            objectOutputStream.writeObject(new Demo("韩啊哈", 12));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class Demo implements Serializable {
    private String name;
    private Integer age;

    @Override
    public String toString() {
        return "Demo{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Demo(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

在这里插入图片描述

package com.gyh.io;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class ObjectInputStream_ {
    public static void main(String[] args) {
        read();
    }

    public static void read() {
        String filePath = "E:\\idea_java_projects\\io\\data.dat";
        ObjectInputStream objectInputStream = null;
        try {
            objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
            // 说明
            // 1. 读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致
            // 2. 否则会出现异常
            int num = objectInputStream.readInt();
            String str = objectInputStream.readUTF();
            Demo d = (Demo) objectInputStream.readObject();
            System.out.println(num);
            System.out.println(str);
            System.out.println(d);

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

8.3 注意事项和细节说明

在这里插入图片描述

九、标准输入输出流

在这里插入图片描述

在这里插入图片描述

package com.gyh.io;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class InputAndOutput {
    public static void main(String[] args) {
        // System 类的 public final static InoutStream in = null;
        // System.in 编译类型 InputStream
        // System.in 运行类型 BufferedInputStream
        // 表示标准输入  键盘
        System.out.println(System.in.getClass());

        // 解读
        // 1. System.out public final static PrintStream out = null;
        // 2. 编译类型 PrintStream
        // 3. 运行类型 PrintStream
        // 4. 表示标准输出  显示器
        System.out.println(System.out);
    }
}

十、转换流-InputStreamReader 和 OutputStreamWriter

10.1 案例引入

在这里插入图片描述

package com.gyh.io;


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

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Transformation {
    public static void main(String[] args) {
        // 读取 e2.txt 文件到程序
        // 思路
        // 1. 创建字符输入流 BufferedReader [处理流]
        // 2. 使用 BufferedReader 对象读取 e2.txt
        // 3. 默认情况下,读取文件是按照 UTF-8 编码的
        // 4. 若使用 BufferedReader 直接读取非UTF-8 编码的字符信息,会乱码
        BufferedReader bufferedReader = null;
        String content;
        try {
            bufferedReader = new BufferedReader(new FileReader("E:\\idea_java_projects\\io\\e3.txt"));
            while ((content = bufferedReader.readLine()) != null) {
                System.out.println(content);
            }

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

10.2 转换流介绍

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

10.3 应用案例

在这里插入图片描述

package com.gyh.io;


import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Transformation {
    public static void main(String[] args) {
        read02();
    }

    public static void read01() {
        // 读取 e2.txt 文件到程序
        // 思路
        // 1. 创建字符输入流 BufferedReader [处理流]
        // 2. 使用 BufferedReader 对象读取 e2.txt
        // 3. 默认情况下,读取文件是按照 UTF-8 编码的
        // 4. 若使用 BufferedReader 直接读取非UTF-8 编码的字符信息,会乱码
        BufferedReader bufferedReader = null;
        String content;
        try {
            bufferedReader = new BufferedReader(new FileReader("E:\\idea_java_projects\\io\\e3.txt"));
            while ((content = bufferedReader.readLine()) != null) {
                System.out.println(content);
            }

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

    public static void read02() {
        String dataPath = "E:\\idea_java_projects\\io\\e3.txt";
        BufferedReader bufferedReader = null;
        String content;
        try {
            // 解读
            // 1. 把 FileInputStream 转成 InputStreamReader
            // 2. 指定编码 GBK
//            input = new InputStreamReader(new FileInputStream(dataPath), Charset.forName("GBK"));
            // 3. 把 InputStreamReader 传入 BufferedReader
//            bufferedReader = new BufferedReader(input);
            // 4. 将 2 和 3 合在一起
            bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(dataPath), Charset.forName("GBK")));
            while ((content = bufferedReader.readLine()) != null) {
                System.out.println(content);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

package com.gyh.io;

import java.io.*;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Transformer02 {
    public static void main(String[] args) {
        write();
    }

    public static void write() {
        String dataPath = "E:\\idea_java_projects\\io\\e4.txt";
        BufferedWriter bw = null;

        try {
            bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dataPath), "gbk"));
            bw.write("hello,韩顺平教育");
            bw.newLine();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

十一、打印流-PrintStream 和 PrintWriter

在这里插入图片描述

// 字节打印流
package com.gyh.io;

import java.io.IOException;
import java.io.PrintStream;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        PrintStream out = System.out;
        // 在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器
        out.print("john, hello");
        // 因为print底层使用的是write,所以我们可以直接调用write进行打印/输出
        out.write("john, hello".getBytes());
        out.close();

        // 我们可以修改打印流输出的位置/设备
        String infoPath = "E:\\idea_java_projects\\io\\e5.txt";
        System.setOut(new PrintStream(infoPath));
        System.out.println("asdaf1");
        System.out.println("asdaf2");

    }
}
// 字符打印流
package com.gyh.io;

import java.io.FileNotFoundException;
import java.io.PrintWriter;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class PrintWriter_ {
    public static void main(String[] args) throws FileNotFoundException {
        String infoPath = "E:\\idea_java_projects\\io\\e5.txt";
        PrintWriter printWriter = new PrintWriter(infoPath);
        printWriter.write("你好");
        printWriter.close();// flush + 关闭流才会将数据写入
    }
}

十二、Properties类

在这里插入图片描述

package com.gyh.io;

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

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Properties01 {
    public static void main(String[] args) {
        read01();
    }
    
    // 传统方法
    public static void read01() {
        String path = "E:\\idea_java_projects\\io\\mysql.properties";
        BufferedReader bufferedReader = null;
        String content;
        try {
            bufferedReader = new BufferedReader(new FileReader(path));
            while ((content = bufferedReader.readLine()) != null) {
                String c = content.split("=")[1];
                System.out.println(c);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

12.1 基本介绍

在这里插入图片描述

12.2 基本方法

在这里插入图片描述

在这里插入图片描述

// 案例1
package com.gyh.io;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Properties02 {
    public static void main(String[] args) throws IOException {
        // 1. 使用 Properties 类来读取mysql.properties 文件
        Properties properties = new Properties();
        // 2. 加载指定配置文件
        properties.load(new FileReader("E:\\idea_java_projects\\io\\mysql.properties"));
        // 3. 把k-v显示到控制台
        properties.list(System.out);
        // 4. 根据 key 获取对应的 value
        String value = properties.getProperty("user");
        System.out.println(value);

    }
}
// 案例2、3
package com.gyh.io;

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Properties03 {
    public static void main(String[] args) throws IOException {
        // 使用 Properties 类来创建配置文件,修改配置文件内容
        Properties properties = new Properties();
        // 创建
        // 1. 如果该文件没有k就是创建
        // 2. 如果该文件有 key ,就是修改
        /*
        * Properties 父类 是Hashtable,底层就是 Hashtable 核心方法
        *
        * public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (value == null) {
                throw new NullPointerException();
            }

            // Makes sure the key is not already in the hashtable.
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % tab.length;
            @SuppressWarnings("unchecked")
            Entry<K,V> entry = (Entry<K,V>)tab[index];
            for(; entry != null ; entry = entry.next) {
                if ((entry.hash == hash) && entry.key.equals(key)) {
                    V old = entry.value;
                    entry.value = value;
                    return old;
                }
            }

            addEntry(hash, key, value, index);
            return null;
        }
        *
        * */
        properties.setProperty("charset", "utf-8");
        properties.setProperty("user", "tom"); // 注意保存时,是中文的 unicode 码值
        properties.setProperty("pwd", "abc111");

        // 将 k-v 存储文件中即可
        properties.store(new FileOutputStream("E:\\idea_java_projects\\io\\mysql2.properties"), null);
        System.out.println("保存配置文件成功~");

    }
}


十三、细节

  • 在java中是处理数据传输的对象
  • 对于 BufferedXXX的输出流,使用时需使用 close 方法(或 flush 方法)才会把字符内容真正写出

13.1 Java中IO流-字节数组拷贝之BufferedInputStream和BufferedOutputStream

https://blog.csdn.net/u011541946/article/details/81124242 — Java中IO流-17-字节数组拷贝之BufferedInputStream和BufferedOutputStream

这篇来学习Java中利用缓存区来进行文件读写操作。一个输入流缓存(BufferedInputStream)和输出流缓存(BufferedOutputStream),理解了其中一个,另外一个就也理解了。下面,我们先看看BufferedInputStream这个类的API介绍和源码实现。
1.BufferedInputStream的原理
在这个类的API中,可以看到这么一句描述的话:在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。那么,我们就看看它的底层实现原理。打开BufferedInputStrea源码,可以找到这么一个成员变量:DEFAULT_BUFFER_SIZ=8192,这个表示缓冲区大小是8kb而且,底层是一个字节数组实现的。
2. BufferInputStream和BufferedOutputStream实现文件拷贝代码
我们直接来一个简单代码,然后来分析注意点和总结特点。

package io;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class Demo4_BufferCopy {
 
    public static void main(String[] args) throws IOException {
        
        FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\jenkins.war");
        FileOutputStream fos = new FileOutputStream("copy.war");
        //创建缓冲区,对输入流进行包装
        BufferedInputStream bis = new BufferedInputStream(fis);
        //创建缓冲区,对输出流进行包装
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        
        int b;
        while ( (b = bis.read()) != -1) {
            bos.write(b);
        }
        //关闭输入流缓冲区
        bis.close();
        //关闭输出流缓存区
        bos.close();
        
    }
 
}

运行之后,刷新Eclipse项目,可以看到copy.war文件复制成功。注意上面,之后关闭的是输入流缓冲区对象和输出流缓冲区对象,而不是输入流和输出流对象,这点和前面有一点区别。原因也很简单,缓冲区对象本来就是包装了对应的输入流或者输出流,关闭了缓冲区,自然把包装里面对象也给一同关闭。
3.为什么要加入缓存思想
这里面涉及到一个装饰器和设计模式的概念,后面我们来学习。很明显,字节流一次读写一个数组的速度肯定要比一次读写一个字节的速度要快,效率高。缓冲区底层就是数组,这个我们在StringBuffer这个类也可以找到这种设计思想。
4.BufferedInputStream缓冲区具体原理
原理是BufferedInputStream底层用了一个数组,默认大小是8192个字节,也就是BufferedInputStream一次性会从文件读取8192个字节,然后返回给程序一个字节,程序在读取8192个字节之前不需要再次去访问和读取文件,直接从缓冲区读。直到缓冲区所有的都读取过,然后再去读取8192个字节,一直这样进行下去,直到任务结束。同样的BufferedOutputStream也是内置一个数组,默认大小也是8192字节。程序向流中写出字节时,不会直接写到文件,而是先写入到缓冲区,直到缓冲区写满,BufferedInputStream才会一次性把数据写入到文件中

13.2 Java中IO流-flush和close方法的区别

https://blog.csdn.net/u011541946/article/details/81150610 — Java中IO流-18-flush和close方法的区别

本篇来学习一个小的知识点,flush方法和close方法的区别。前面我们介绍了和使用了close方法,知道是用来关闭流的操作,但是并没有介绍flush方法,字面意思的刷新的意思。下面我们来先看看一个例子,然后引出flush方法。

  1. 如果不关闭流执行代码
package io;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class Demo4_BufferCopy {
 
    public static void main(String[] args) throws IOException {
        
        FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\jenkins.war");
        FileOutputStream fos = new FileOutputStream("copy.war");
        //创建缓冲区,对输入流进行包装
        BufferedInputStream bis = new BufferedInputStream(fis);
        //创建缓冲区,对输出流进行包装
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        
        int b;
        while ( (b = bis.read()) != -1) {
            bos.write(b);
        }
        //关闭输入流缓冲区
        //bis.close();
        //关闭输出流缓存区
        //bos.close();
        
    }
 
}

执行上面代码,你可以对比copy.war文件的大小和jenkins.war区别,发现copy.war文件会比原文件jenkins.war要小一些。为什么会发生这个情况呢,答案就是在close方法了。在Eclipse中,查看close方法的源码如下:

@SuppressWarnings("try")
    public void close() throws IOException {
        try (OutputStream ostream = out) {
            flush();
        }
    }

通过看close方法的源码,发现close方法里面包含一个flush方法。flush就是刷新缓冲区的功能,所以,我们可以总结close方法的作用或者特点是:具备刷新功能,在关闭流之前,就会先刷新一次缓存区,将缓冲区的字节全都刷新到文件上,再关闭流。这里,我们来解释下上面代码,没有close方法,也就是没有进行刷新操作,文件为什么会变小。文件变小,说明了还有一部分内容没有完成写入到文件。前面一篇,我们介绍了缓冲区默认大小是8192字节,上面文件在最后一次写入到文件的缓冲区里,里面字节数没有8192大小,所以不会触发自动写入操作,从而留下一部分字节没有写入到文件。只要文件不是8192字节的N倍大小,如果最后不进行close操作,肯定会丢失一部分数据。

2.用flush方法代替close方法
为了验证close方法包含flust,我们用flush方法代替close来进行测试下。

package io;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class Demo4_BufferCopy {
 
    public static void main(String[] args) throws IOException {
        
        FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\jenkins.war");
        FileOutputStream fos = new FileOutputStream("copy.war");
        //创建缓冲区,对输入流进行包装
        BufferedInputStream bis = new BufferedInputStream(fis);
        //创建缓冲区,对输出流进行包装
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        
        int b;
        while ( (b = bis.read()) != -1) {
            bos.write(b);
        }
        //关闭输入流缓冲区
        //bis.close();
        //关闭输出流缓存区
        //bos.close();
        bos.flush();
    }
 
}

如果你继续注销flush方法,还是发现拷贝之后文件变小。这里来总结下flush功能,主要就是刷新的作用,刷新完还可以继续写操作,这个典型的应用可以脑补下QQ即时聊天场景就好

3.flush和close区别
简单来说,close包含flush功能,但是flush具备刷新完,还可以继续写操作,close执行完了就流关闭了,不能再写入,所以,不能用close来代替flush。为了证明这个结论,可以执行下面代码

package io;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class Demo4_BufferCopy {
 
    public static void main(String[] args) throws IOException {
        
        FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\jenkins.war");
        FileOutputStream fos = new FileOutputStream("copy.war");
        //创建缓冲区,对输入流进行包装
        BufferedInputStream bis = new BufferedInputStream(fis);
        //创建缓冲区,对输出流进行包装
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        
        int b;
        while ( (b = bis.read()) != -1) {
            bos.write(b);
            bos.flush();
            //bos.close();
        }
        //关闭输入流缓冲区
        //bis.close();
        //关闭输出流缓存区
        //bos.close();
        
    }
 
}

我在每一次写入文件操作后,里面执行刷新一次,当然这样写的后果就是拷贝执行过程太慢,耗时。但是如果这里尝试用close方法来代替flush,就会报已经关闭了流,不能再对流进行操作的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ModelBulider

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值