Java-IO流

IO流:存储和读取数据的解决方案,用于读写文件中的数据。

IO流使用原则:什么时候使用什么时候创建,什么时候不用,什么时候关闭。

IO流的分类

1)按照流向分:输出流(从程序写到文件中),输入流(从文件写到程序中)。

2)按照操作文件的类型:字节流(可以操作所有类型的文件),字符流(只能操作纯文本文件)

1.IO流体系的基本流

下面四个都是抽象类,不能直接创建对象。

1.1字节流

1)FileOutputStream

FileOutputStream:操作本地文件的字节输出流,可以把程序中的数据写到本地文件中。

FileOutputStream写数据的三种方式:

FileOutputStream进行换行操作:Windows:\r\n Linux:\n Mac:\r

FileOutputStream进行续写操作:如果想要续写打开续写开关即可,创建对象的第二个参数就是续写开关,默认为false,表示关闭续写,此时创建文件会清空文件,手动传递false,表示打开续写,此时就不会再清空文件,而是接在后面写。

步骤:

1>创建字节输出流对象

参数是字符串表示的路径或者是File对象都可以;如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的;如果文件已经存在,则会清空文件

2>写数据

write方法的参数是整数,但是实际写到本地文件中的是整数在ASCII上对应的字符

3>释放资源

每次使用完之后都要释放资源,释放相当于解除资源的占用。

2)FileInputStream

FileInputStream:操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中。

FileInputStream写数据的两种方式:

一次读取一个字节数组的数据,每次读取会尽可能把数组装满。数组大小尽可能为1024的整数倍

步骤:

1>创建字节输入流对象

如果文件不存在,直接报错

2>读数据

一次读取一个字节,读出来的是ASCII上对应的数字,读到文件末尾了,read方法返回-1

3>释放资源

1.2字符集

1)ASCII字符集

2)GBK

存储汉字规则:1>汉字使用两个字节进行存储 2>高位字节二进制一定是以1开头,转成十进制之后是一个负数 3>GBK汉字编码规则不需要变动

核心1:GBK中,一个英文字母一个字节,二进制第一位是0

核心2:GBK中,一个中文汉字两个字节,二进制第一位是1

3)Unicode

UTF-8编码规则:用1-4个字节保存

ASCII采用一个字节二进制的第一位是0;简体中文三个汉字

1.3字符流

字符流的底层是字节流(字符流=字节流+字符集)

特点:

输入流:一次读一个字节,遇到中文时,一次读多个字节

输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写道文件中

使用场景:对于纯文本文件进行读写操作

1)FileReader

步骤:

1>创建字符输入流对象

如果文档不存在,就会直接报错

2>读取数据

按字节进行读取,遇到中文,一次读多个字节,读取后解码成十进制,返回一个整数;读到文件末尾时,read方法返回-1

3>释放资源

2)FileWriter

构造方法:

没有打开续写开关就会清空文件,使用FileReader读取文件时,先装满8192个字节数组,所以先读取缓冲区的字节数组内容,即使使用的FileWriter/FileOutputStream清空了内容,使用FileReader读取时还是可以读取缓冲区已经存在的数据,剩下的未装进缓冲区的数据无法读取。

字节流和字符流的使用场景

字节流:拷贝任意类型的文件

字符流:读取纯文本文件中的数据;往纯文本文件中写入数据

2.IO流体系的高级流
2.1缓冲流

1)字节缓冲流

原理:底层自带了长度为8192的缓冲区,显著提高字节流的读写性能。对于字符流来说不明显

构造方法:

字节缓冲流提高效率的原理:

不断从输入的缓冲区运输到输出的缓冲区里面,这里的过程都是在内存里面进行的,内存运行的速度非常快,几乎忽略不计,节省的时间是读写时和硬盘交流的时间。

2)字符缓冲流

构造方法:

一次读一整行,遇到回车换行结束,但是不会把回车换行读到内存中。

2.2转换流

转换流是字符流和字节流之前的桥梁。

作用:1)指定字符集读写 2)字节流想要使用字符流中的方法

字符转换输入流:InputStreamReader

字符转换输出流:OutputSreamWriter

2.3序列化流

序列化流:也叫对象操作输出流,可以把Java中的对象写到本地文件中

构造方法:

成员方法:

序列化流使用输出流将对象保存到文件时会出现NotSerializationException异常,需要让对象的JavaBean类实现Serializable接口

Serializable接口里面是没有抽象方法的,是标记型接口,一旦实现这个接口,那么就表示当前的类可以被序列化

反序列化流:也叫对象操作输入流,可以把序列化到本地文件中的对象,读取到程序中来。

构造方法:

成员方法:

java 复制代码
public static void main(String[] args) throws IOException, ClassNotFoundException {

        //创建对象
        Student stu = new Student("zhangsan",23);

        //创建序列化流的对象/操作对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/heimaPractice/FileAndIO/a.txt"));

        //写出数据
        oos.writeObject(stu);

        oos.close();

        //创建反序列化流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/heimaPractice/FileAndIO/a.txt"));

        //读取数据
        Student o = (Student)ois.readObject();

        //打印对象
        System.out.println(o);

        ois.close();
    }
//实现接口
class Student implements Serializable{}
2.4打印流

打印流不能读只能写,分为字节打印流和字符打印流。

分类:打印流一般是指PrintStream,PrintWriter

特点1:打印流纸草纸文件目的地,不操作数据源

特点2:特有的写出方法可以实现,数据原样写出

特点3:特有的写出方法,可以实现自动刷新,自动换行。

1)字节打印流:

构造方法:

字节流底层没有缓冲区,开不开自动刷新都一样

成员方法:

2)字符打印流

字符打印流底层有缓冲区,想要自动刷新需要开启

构造方法:

成员方法:

2.5压缩流/解压缩流

解压缩流:ZipInputStream

解压的本质就是把每一个ZipEntry按照层级拷贝到本地另一个文件夹当中

java 复制代码
public static void unzip(String src, String dest) throws IOException {
        //创建解压缩六来读取压缩包中的数据
        ZipInputStream zip = new ZipInputStream(new FileInputStream(src));

        ZipEntry entry;
        while((entry=zip.getNextEntry())!=null){
            System.out.println(entry.getName());
            if(entry.isDirectory()){
                //如果是文件夹,在目的地dest处创建一个同样的文件夹
                File file = new File(dest,entry.toString());
                file.mkdir();
            } else {
                //如果是文件,需要读取到压缩包中的文件,并把他存放到目的地dest中(需要按照层级目录进行存放)
                FileOutputStream fos = new FileOutputStream(new File(dest,entry.getName()));
                int b;
                while((b=zip.read())!=-1){
                    fos.write(b);
                }
                fos.close();
                //表示压缩包里面的一个文件处理完毕
                zip.closeEntry();;
            }
        }
    }

压缩流:ZipOutputStream

压缩本质:把每一个文件/文件夹堪称ZipEntry对象放到压缩包中

java 复制代码
/**
     * 压缩--单个文件
     * @param src
     * @param dest
     */
    public static void tozip(File src, File dest) throws IOException {
        //创建压缩流关联压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,src.getName().split("\\.")[0]+".zip")));
        //创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹
        ZipEntry entry = new ZipEntry(src.getName());
        //把ZipEntry对象放到压缩包当中
        zos.putNextEntry(entry);
        //把src文件中的数据写到压缩包当中
        FileInputStream fis = new FileInputStream(src);
        int b;
        while((b=fis.read())!=-1){
            zos.write(b);
        }
        fis.close();
        zos.closeEntry();
        zos.close();
    }

    /**
     * 压缩--多个文件
     * @param src
     * @param dest
     */
    public static void tozip2(File src, File dest) throws IOException {
        //创建压缩流关联压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,src.getName().split("\\.")[0]+".zip")));
        //获取src的每一个文件,变成zipEntry对象,放入到压缩包当中
        toZip(src,zos,src.getName());
        zos.close();
    }

    /**
     * 递归压缩--获取src里面的每一个文件,变成ZipEntry对象,再放入压缩包当中
     * @param src --数据源
     * @param zos --压缩流
     * @param name --压缩包内部路径
     */
    public static void toZip(File src,ZipOutputStream zos,String name) throws IOException {
        File[] files = src.listFiles();
        for (File file : files) {
            if(file.isFile()){
                //变成ZipEntry对象放入压缩包--这个路径应该是aaa\\a.txt
                ZipEntry entry = new ZipEntry(name+"\\"+file.getName());
                zos.putNextEntry(entry);
                //读取文件中的数据写到压缩包
                FileInputStream fis = new FileInputStream(file);
                int b;
                while((b=fis.read())!=-1){
                    zos.write(b);
                }
                fis.close();
                zos.closeEntry();
            } else {
                toZip(file,zos,name+"\\"+file.getName());
            }
        }
    }
2.6Commons-io

Commons-io是apache开源基金组织提高的一组有关IO操作的开源工具包

作用:提高IO流的开发效率

1.7Hutool工具包

拓展:配置文件

好处1:可以把软件的设置永久化存储

好处2:需要修改参数时,不需要改动代码,直接修改配置文件即可

properties是一个双列集合,拥有Map集合的所有特点

重点:有一些特有的方法,可以把集合中的数据,按照键值对的形式写到配置文件当中。也可以把配置文件中的数据读取到集合当中。

相关推荐
NiceCloud喜云3 小时前
Claude API 流式输出(SSE)实战:从打字机效果到工具调用全流程
java·前端·ide·人工智能·chrome·intellij-idea·状态模式
故事和你913 小时前
洛谷-【图论2-3】最小生成树2
开发语言·数据结构·c++·算法·动态规划·图论
SimonKing3 小时前
别再死磕 Elasticsearch 了,这个轻量级搜索引擎更香
java·后端·程序员
asdfg12589633 小时前
一文理解“工程化思维”
java·编程思想
阿昌喜欢吃黄桃3 小时前
并发线程工具类分享
java·线程池·多线程·并发·juc
Rsun045513 小时前
try-with-resources跟try-catch-finally的区别
java
计算机安禾3 小时前
【c++面向对象编程】第35篇:构造函数与异常:如何避免资源泄露?
开发语言·javascript·c++·算法·性能优化
桀人3 小时前
类和对象——下
开发语言·c++
一只大袋鼠3 小时前
Git (三):Tag 标签管理、图形工具、IDEA 集成与 GitLab 私有化部署
开发语言·git·gitlab