学习笔记_IO流

一、文件和文件流

1. 什么是文件

  文件是保存数据的地方,比如word文档,txt文件,excel文件。文件既可以保存图片,也可以保存视频,声音等等。

2. 文件流

  文件在程序中是以流的形式来操作的。
在这里插入图片描述

流:数据在数据源(文件)和程序(内存)之间经历的路径

3.常用的文件操作

  此处已经介绍了一些常用的文件操作,可先观看此处,点此链接

二、IO流原理及流的分类

1. IO流基本知识

  • Java I/O(Input/Output)是指输入/输出操作。
  • Java 中的流都位于 java.io 包下
  • 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
  • 输出output:将程序(内存)中的数据输出到磁盘、光盘等存储设备中。

2. Java IO流原理

  流是用于处理输入和输出的抽象机制,它提供了一种与底层系统通信的方法。Java I/O流是基于字节字符的操作,它将数据存储在内存中,以便在需要时读取或写入数据。
  Java I/O 流的工作原理是通过输入和输出流进行数据传输。输入流从源中读取数据,并将其存储在内存中,然后输出流从内存中读取数据,并将其写入到目标位置中。Java I/O 流的实现是基于装饰器模式的,它允许用户使用不同的装饰器来增强流的功能。

  IO 流体系中大量使用了装饰器模式,让流具有更强的功能、更强的灵活性。比如:

FileInputStream  fis = new FileInputStream(src);
BufferedInputStream  bis = new BufferedInputStream(fis);

  显然BufferedInputStream装饰了原有的InputStream,让普通的InputStream也具备了缓存功能,提高了效率。

3. 流的分类

  • 按照流向分: 输入流   输出流
  • 按照单位分: 字节流   字符流
  • 按照角色分: 节点流   处理流

4.IO流的四个顶级父类

(抽象基类)字节流字符流
输入流InputStreamReader
输出流OutputStream0Writer

  Java中IO流涉及到的类,都是由以上四个抽象基类派生的。如下图所示:

在这里插入图片描述

三、常用类的使用

1.FileInputStream

实现一:现在要使用FileInputStream读取本地D盘中的hello.txt文件

请添加图片描述在这里插入图片描述

实现代码:

@Test
    public void readFile01 () {
        String filePath = "D:\\hello.txt";
        int readData = 0;
        FileInputStream fileInputStream = null;
        try {
            //创建 FileInputStream 对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);
            //从此输入流中读取一个数据字节。如果没有输入可用,则此方法将阻塞。
            //如果返回 -1,表示去读取完毕。
            while ((readData = fileInputStream.read()) != -1) {
                System.out.print((char)readData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

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

结果:
在这里插入图片描述

实现二:使用read(byte [ ])方法提高读取效率

  代码如下:

 /**
     * read(byte []) 方法:
     *      1、从此输入流中一次性将最多 b.length 个字节的数据读入一个 byte 数组中。
     *      2、如果返回 -1,表示已经读取完毕。
     *      3、如果读取正常,返回实际读取的字节数
     */
@Test
    public void readFile02 () {
        String filePath = "D:\\hello.txt";
        int readData = 0;
        //字节数组
        byte [] buf = new byte[8]; //一次读取8个字节
        int readLen = 0;
        FileInputStream fileInputStream = null;
        try {
            //创建 FileInputStream 对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);
            //从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。在某些输入可用之前,此方法将阻塞。
            //如果返回 -1,表示去读取完毕。
            //如果读取正常,返回实际读取的字节数
            while ((readLen = readData = 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();
            }
        }
    }

  结果:为了方便看出区别,我在每次输出后面加了一个空格,每次输出8个字节,此处可以看到第一次输出是以 o 结尾
在这里插入图片描述

2.FileOutputStream

实现一:使用FileOutputStream在 hello2.txt 文件中写入“Hello,World”

实现代码:

/**
     * 演示使用FileOutputStream 将数据写到文件中
     * 如果文件不存在,则创建文件
     *  说明:
     *      如果使用 :new FileOutputStream(filePath) 创建方式,当写入内容时,会覆盖原先的内容
     *      如果使用: new FileOutputStream(filePath,true) 创建方式,当写入内容时,`会追加到原先的内容之后,并不是覆盖`
     */

  实现内容追加使用的是FileOutputStream的另一个构造方法,如下所示:
在这里插入图片描述

@Test
    public void writeFile() {

        //创建 FileOutputStream 对象
        String filePath = "D:\\hello2.txt";
        FileOutputStream fileOutputStream = null;

        try {
            //得到 FileOutputStream 对象
            fileOutputStream = new FileOutputStream(filePath);
            //写入一个字节
            //fileOutputStream.write('a');
            String str = "hello.world";
            //str.getBytes() 可以吧 字符串 -> 字节数组
            //write(byte[] b, int off, int len) 将len字节从位于偏移量 off的指定字节数组写入此文件流输出
            fileOutputStream.write(str.getBytes(),0,str.length());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

3.组合使用,实现文件拷贝

实现:将D:\Demo下的 开发14截图.png 拷贝到D:\

public class FileCopy {
    public static void main(String[] args) {
        //实现文件拷贝 将D:\\Demo下的 开发14截图.png  拷贝到D:\\
        /**
         * 思路分析
         * 1.创建文件的输入流,将文件读入到程序
         * 2.创建文件的输出流,将读取到的文件数据,写入到指定的文件
         */

        String path1 = "D:\\Demo\\hello.png"; //要拷贝的文件路径
        String path2 = "D:\\hello.png"; //要拷贝到地方的路径

        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;

        byte [] bytes = new byte[1024]; //创建一个byte数组
        int readLen = 0; //每次读取的长度
        try {

            fileInputStream = new FileInputStream(path1);

            fileOutputStream = new FileOutputStream(path2);

            while ((readLen = fileInputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes,0,readLen);
            }
            System.out.println("拷贝成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                //关流
                fileOutputStream.close();
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4.FileReader

实现一:使用FileReader读取本地D盘中的 story.txt 文件

/**
 *  FileReader 常用方法
 *      new FileReader(File/String) 构造方法
 *      read():每次读取单个字符,返回该字符,如果文件到末尾则返回-1
 *      read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
 *  相关API:
 *      new String(char[]): 将char[]转换成String
 *      new String(char[],off,len): 将char[]的指定部分转换成String
 */
public class FileReader01 {
    public static void main(String[] args) {
        String filePath = "D:\\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 {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

结果:
在这里插入图片描述

实现二:使用char[] 数组,提高读取效率

实现代码:

/**
     * 使用字符数组读取文件
     */
    @Test
    public void readFile02() {
        String filePath = "D:\\story.txt";
        FileReader fileReader = null;

        int readLen = 0;
        char[] buf = new char[8]; //创建char[] 数组
        try {
        	//创建FileReader 对象
            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 {
                fileReader.close(); //关流
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

结果:
在这里插入图片描述

5.FileWriter

实现一:使用FileWrite将 “笃志前行,虽远必达” 写入到 D:\note.txt 文件中。

/**
 *  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,off,len):写入字符串的指定部分
 *
 *   注意:对应FileWriter,一定要关闭流,或者刷新(flush)才能真正的把数据写入到文件
 *                      关闭:刷新(flush) + 关闭
 */

public class FileWrite_ {

    public static void main(String[] args) {

        String path = "D:\\note.txt";
        //创建FileWrite对象
        FileWriter fileWriter = null;

        try {
//            fileWriter = new FileWriter(path);//内容覆盖,第二次执行结果:笃志前行,虽远必达
            fileWriter = new FileWriter(path,true);//内容追加,第二次执行结果:笃志前行,虽远必达笃志前行,虽远必达
            fileWriter.write("笃志前行,虽远必达");
//            fileWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (fileWriter != null){
                    fileWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

请添加图片描述请添加图片描述

四、节点流和处理流

节点流

  节点流是直接将源或目标连接到数据源或目标的流,是一个真正的Java IO流对象,代表着一个底层的物理流(如文件、Socket、管道等)。如:FileReader、FileWriter

处理流

  处理流则是在节点流上的一个包装,本身不提供数据传输能力,但加入了许多有用的功能,例如缓冲、转换、过滤等,是对节点流的一种功能增强,使得读写数据更加方便、快捷、高效。如:BufferedReader、BufferedWriter.

  处理流本身不能单独存在,必须要连接在一个节点流上,通过多个处理流的组合,可以构建出复杂而高效的IO数据处理链条。

  一些处理流:

  • BufferedInputStream、BufferedOutputStream(缓冲流)
      字节输入输出流的处理流,可以在读写数据时提高效率,通过缓冲区存储读入的数据,减少与物理介质的交互次数,提高IO性能。

  • BufferedReader、BufferedWriter(缓冲流)
      是字符输入输出流的处理流,与BufferedInputStream、BufferedOutputStream不同的是,它们是基于字符数据的缓存机制,可以读写文本数据以及以行为单位读写数据,可以提高读写数据的效率。

  • DataInputStream、DataOutputStream(基本数据类型流)
      是字节输入输出流的处理流,支持读写Java基本数据类型,如int、double、boolean等。

  • ObjectInputStream、ObjectOutputStream(对象流)
      是字节输入输出流的处理流,支持读写Java对象,可以将Java对象序列化到文件中或从文件中反序列化出来,常常用于Java对象的数据持久化。

  • InputStreamReader、OutputStreamWriter(转换流)
      是字节输入输出流与字符输入输出流之间的桥梁,能够把字节流转换为字符流和字符流转换为字节流,支持字符集编码转换。

  • PrintStream、PrintWriter(打印流)
      是字节输出流和字符输出流的处理流,支持将格式化的数据写到流中,支持输出Java基本类型数据和对象类型数据。

实现一:使用BufferedReader读取文件

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

        String filePath = "D:\\story.txt";
        //创建FileReader 对象
        FileReader fileReader = new FileReader(filePath);
        //创建BufferedReader 对象
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        //读取
        String line; //按行读取,效率高
        // bufferedReader.readLine() 是按行读取文件 返回null,表示文件读取完毕
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }
        //关闭流, 这里只需要关闭 bufferedReader ,因为底层会自动关闭 节点流
        bufferedReader.close();
    }
}

实现二:使用BufferedWriter写入文件

public class BufferedWriter_ {

    public static void main(String[] args) throws IOException {
        String filePath = "D:\\hello.txt";
        //创建FileWriter对象
        FileWriter fileWriter = new FileWriter(filePath);
        //创建BufferedWriter对象
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        bufferedWriter.write("笃志前行,虽远必达");

        //插入一个和系统相关的换行
        bufferedWriter.newLine();
        //此处会在下一行显示
        bufferedWriter.write("笃志前行,虽远必达");
        //关闭流  关闭包装流即可,fileWriter 会在底层自动关闭
        bufferedWriter.close();
    }
}

实现三:拷贝文件

/**
 *  BufferedReader  和   BufferedWriter 是安装字符操作
 *  不要去操作二进制文件,可能会造成文件损坏
 */
public class BufferedCopy {

    public static void main(String[] args) {

        String filePath1 = "D:\\Java\\story.txt";
        String filePath2 = "D:\\story.txt";

        BufferedReader br = null;
        BufferedWriter bw = null;
        String line = null;

        try {
            br = new BufferedReader(new FileReader(filePath1));
            bw = new BufferedWriter(new FileWriter(filePath2));

            //readLine() 读取一行内容,但是没有换行
            while ((line = br.readLine()) != null) {
                //每读取一行就写入
                bw.write(line);
                //插入一个换行
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (bw != null) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

五、Properties类

介绍

  Java中的Properties类是一个键值对集合,通常用来存储和读取配置参数。它继承了Hashtable类,因此提供了Hashtable的所有方法,并增加了一些方便使用的特性,如支持从文件加载和保存属性、默认属性值等。下面是Properties类的详细介绍:

  1. 创建对象:
Properties prop = new Properties();
  1. 存取键值:
// 存储键值对
prop.setProperty("key", "value");

// 根据键获取值
String value = prop.getProperty("key");
  1. 加载属性:
// 从输入流读取属性
InputStream in = new FileInputStream("config.properties");
prop.load(in);

// 从文件读取属性
FileInputStream fis = new FileInputStream("config.properties");
prop.load(fis);

在以上示例中,我们可以通过使用setProperty()方法将键值对添加到Properties对象中。然后,我们可以使用getProperty()方法通过键名称获取相应的值。接着,我们可以使用load()方法从(输入)流中加载属性。

  1. 保存属性:
// 将属性写入到文件中
OutputStream out = new FileOutputStream("config.properties");
prop.store(out, "Configurations");

在以上示例中,我们打开output Stream并指定目标文件,通过调用store()方法将Properties对象中的所有键值对存储到输出流中。此外,第二个参数是可选的注释字符串。

  1. 默认属性值:
Properties defaultProps = new Properties();

// 设置默认属性值
defaultProps.setProperty("key1", "value1");

// 创建属性对象,并将默认值作为参数
Properties props = new Properties(defaultProps);

// 获取属性值
String value = props.getProperty("key1");

通过在初始化Properties对象时传递一个默认属性值对象,我们可以将某些键值对的默认值提前设置。如果在之后存储或获取某个键的值时没有指定具体的值,则相应的缺省值将被使用。

实现:使用Properties 类来读取 jdbc.properties 文件

在这里插入图片描述

public class Properties01 {

    public static void main(String[] args) throws IOException {

        //1.创建Properties对象
        Properties properties = new Properties();
        //2.加载指定配置文件
        properties.load(new FileReader("gao3\\src\\jdbc.properties"));
        //3.把k-v显示在控制台
        properties.list(System.out);
        System.out.println("===================");
        //4.根据key 获取相对应的值
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        System.out.println("用户名:" + user);
        System.out.println("密码:" + password);

    }
}

结果:
请添加图片描述

作者期望

如果能从本篇文章获取到一点知识的话,请为作者点个赞加个油
如果有什么不正确的地方,欢迎指正,评论区交流。

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值