• Java IO流详解


    Java IO流详解

    个人主页:https://blog.csdn.net/hello_list
    今天我们来学习下java中的io部分

    首先我们要知道io指的是什么,输入输出,就是输入输出流,我们在知道就是流又分为两个,输入流和输出流,再从单位上分,又分为字符流和字节流

    • 字节流:以字节为单位,可以读取任何数据
    • 字符流:以字符为单位,只能读写文本数据

    再按功能,又分为节点流和过滤流

    • 节点流:具有实际传输数据的读写功能
    • 过滤流:在节点流的基础上增强功能

    字节输入输出流

    InputStream常用方法

    intavailable() 返回从该输入流中可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。
    voidclose() 关闭此输入流并释放与流相关联的任何系统资源。
    voidmark(int readlimit) 标记此输入流中的当前位置。
    booleanmarkSupported() 测试这个输入流是否支持 markreset方法。
    abstract intread() 从输入流读取数据的下一个字节。
    intread(byte[] b) 从输入流读取一些字节数,并将它们存储到缓冲区 b
    intread(byte[] b, int off, int len) 从输入流读取最多 len字节的数据到一个字节数组。
    voidreset() 将此流重新定位到上次在此输入流上调用 mark方法时的位置。
    longskip(long n) 跳过并丢弃来自此输入流的 n字节数据。

    OutputStream常用方法

    voidclose() 关闭此输出流并释放与此流相关联的任何系统资源。
    voidflush() 刷新此输出流并强制任何缓冲的输出字节被写出。
    voidwrite(byte[] b)b.length字节从指定的字节数组写入此输出流。
    voidwrite(byte[] b, int off, int len) 从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流。
    abstract write(int b) 将指定的字节写入此输出流

    我们最常用的是实现他们的子类,FileInputStream和FileOutputStream,我们做一个简单的应用

    我们首先用FileOutputStream创建一个文件并写入内容

    public class FileOutputStreamTest {
        public static void main(String[] args) throws IOException {
            FileOutputStream fileOutputStream = new FileOutputStream("E://hello.txt");
            fileOutputStream.write("hello".getBytes());
            // 刷新磁盘空间
            fileOutputStream.flush();
            // 关闭字节流
            fileOutputStream.close();
            System.out.println("文件写入成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    效果

    在这里插入图片描述

    FileInputStream读取文件

    public class FileInputStreamTest {
        public static void main(String[] args) throws Exception {
            File file = new File("E:\\hello.txt");
    //        System.out.println(file.exists());
    //        BufferedReader fis = new BufferedReader(new InputStreamReader(System.in));
            FileInputStream fis = new FileInputStream(file);
            int count = -1;
            byte[] buff = new byte[1024];
            while ((count = fis.read(buff)) != -1) {
                System.out.println(new String(buff, 0, count,"UTF-8"));
            }
            fis.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    字节缓冲流

    我们还可以使用具有缓存效果的字节流:BufferedInputStream和BufferedOutputStream,具有缓存,可以提高效率

    BufferedOutputStream读取文件

    public class BufferedOutputStreamTest {
        public static void main(String[] args) throws Exception {
            // 1、创建流
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E://hello.txt"));
            // 2、写入文件内容
            bos.write("hello,我是学习日记".getBytes());
            // 3、刷新磁盘,关闭流
            bos.flush();
            bos.close();
            System.out.println("写入文件完成");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    BufferedInputStream读取文件

    public class BufferedInputStreamTest01 {
        public static void main(String[] args) throws Exception {
        // 1、创建流
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E://hello.txt"));
            int len = -1;
            byte[] buffer = new byte[1024];
            // 2、通过流读取内容
            while ((len=bis.read(buffer))!=-1){
                System.out.println(new String(buffer,0,len,"UTF-8"));
            }
            // 3、关闭流
            bis.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    对象流

    我们还可以使用对象流创建和保存对象:ObjectOutputStream和ObjectInputStream

    使用ObjectOutputStream保存对象

    我们首先创建一个student学生类

    package com.xuexi.io;
    
    
    import java.io.Serializable;
    
    // 必须实现序列化接口
    public class Student implements Serializable {
        String name;
        Integer age;
    
        @Override
        public String toString() {
            return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
        }
    
        public Student(String name, Integer age) {
            this.name = name;
            this.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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    通过对象流可以保存对象持久化

    public class ObjectOutputStreamTest {
        public static void main(String[] args) throws Exception {
            Student xuexi = new Student("学习日记", 18);
            // 1、创建流
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\hello.txt"));
            // 2、写入内容
            oos.writeObject(xuexi);
            // 3、关闭流 close的时候会自动进行flush操作
            oos.flush();
            oos.close();
            System.out.println("保存对象成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    我们可以看下保存的对象是什么样子,其实可以看出来,就是我们保存的样子

    在这里插入图片描述

    还可以使用ObjectInputStream读取对象,反序列化

    public class ObjectInputStreamTest {
        public static void main(String[] args) throws Exception {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\hello.txt"));
            Student xuexi = (Student)ois.readObject();
            ois.close();
            System.out.println(xuexi);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    可以看到读取成功对象,这样也是创建对象的一种方式

    在这里插入图片描述

    字符流

    Reader和Writer这里两大接口

    其实跟之前的字节流一样,我们可以直接使用FileReader和FileWriter

    FileWriter写入文件

    public class FileWriterTest {
        public static void main(String[] args) throws IOException {
            FileWriter fw = new FileWriter("E:\\hello.txt");
            fw.write("hello,我是学习日记");
            fw.flush();
            fw.close();
            System.out.println("写入文件成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    FileReader读取文件

    public class FileReaderTest {
        public static void main(String[] args) throws IOException {
            FileReader fr = new FileReader("E:\\hello.txt");
            int len = -1;
            char[] buffer = new char[1024];
            while ((len = fr.read(buffer))!=-1){
                System.out.println(new String(buffer,0,len));
            }
            fr.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    字符缓冲流

    同样我们肯定还有具有缓冲效果的字符缓冲流,可以提高读写效率:BufferedReader和BufferedWriter

    BufferedWriter写入文件

    public class BufferedWriterTest {
        public static void main(String[] args) throws IOException {
            BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\hello.txt"));
            bw.write("hello,我是学习日记");
            bw.flush();
            bw.close();
            System.out.println("文件写入完毕");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    BufferedReader读取文件

    public class BufferedReaderTest {
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new FileReader("E:\\hello.txt"));
            int len = -1;
            char[] buffer = new char[1024];
            while ((len = br.read(buffer))!=-1){
                System.out.println(new String(buffer,0,len));
            }
            br.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    字符编码

    • ISO-8859-1收录除了ASCII外,还包括西欧、希腊语、泰语、阿拉伯语等对应的文字符号;

    • UTF-8:针对Unicode码表的可变长度字符编码

    • GB2312:简体中文

    • GBK:简体中文,扩充

    • BIG5台湾,繁体中文

    打印流PrintWriter

    PrintWriter顾名思义 打印流,支持数据原样直接打印,并且封装了print和println支持写入后换行

    public class PrintWriterTest {
        public static void main(String[] args) throws FileNotFoundException {
            PrintWriter pw = new PrintWriter("D:\\hello.txt");
            pw.println(12);
            pw.println(false);
            pw.println(123.123);
            pw.println('a');
            pw.println("hello,我是学习日记");
            pw.close();
            System.out.println("文件写入完成");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    我们可以看下写入内容

    在这里插入图片描述

    转换流

    我们知道字符流比字节流更大,那我们也可以讲字节流转换位字符流,同时可以设置字符编码格式

    我们就需要用到转换流:InputStreamReader和OutputStreamWriter

    OutputStreamWriter字节流转换为字符流写入文件

    public class OutputStreamWriterTest {
        public static void main(String[] args) throws IOException {
            FileOutputStream fos = new FileOutputStream("E:\\hello.txt");
            OutputStreamWriter osr = new OutputStreamWriter(fos,"UTF-8");
            osr.write("hello,我是学习日记");
            osr.flush();
            osr.close();
            fos.close();
            System.out.println("文件写入成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    InputStreamReader读取文件

    public class OutputStreamWriterTest {
        public static void main(String[] args) throws IOException {
            FileInputStream fis = new FileInputStream("E:\\hello.txt");
            InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
            int len = -1;
            char[] buffer = new char[1024];
            while ((len = isr.read(buffer))!=-1){
                System.out.println(new String(buffer,0,len));
            }
            isr.close();
            fis.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    File文件

    看下File文件的使用,我们在之前通过流创建文件的时候就直接写好了绝对路径地址,如果文件不存在就会自动创建文件,我们可以发现其实接口里面也是帮我们new了一个File文件
    在这里插入图片描述

    使用起来呢其实都很简单,调用一些方法,参数什么的,大家可以参考着API文档去使用就可以了

    在这里插入图片描述

    FileFilter

    这里我们再提一个FileFilter过滤器接口,顾名思义可以用来做一些过滤的操作

    public class FileFilterTest {
        public static void main(String[] args) {
            File file = new File("E:\\MarkDown");
            File[] files = file.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    if (pathname.getName().endsWith(".md"))
                        return true;
                    return false;
                }
            });
            for (int i = 0; i < files.length; i++) {
                System.out.println(files[i]);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    上手试一下,然后多看着api文档调用下,就可以了,很简单,不过一定要上手哦

    ProPerties

    properties其实就是属性集合,我们经常用来做配置文件

    我们可以看下有哪些方法:

    Modifier and TypeMethod and Description
    StringgetProperty(String key) 使用此属性列表中指定的键搜索属性。
    StringgetProperty(String key, String defaultValue) 使用此属性列表中指定的键搜索属性。
    voidlist(PrintStream out) 将此属性列表打印到指定的输出流。
    voidlist(PrintWriter out) 将此属性列表打印到指定的输出流。
    voidload(InputStream inStream) 从输入字节流读取属性列表(键和元素对)。
    voidload(Reader reader) 以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。
    voidloadFromXML(InputStream in) 将指定输入流中的XML文档表示的所有属性加载到此属性表中。
    EnumerationpropertyNames() 返回此属性列表中所有键的枚举,包括默认属性列表中的不同键,如果尚未从主属性列表中找到相同名称的键。
    voidsave(OutputStream out, String comments) 已弃用 如果在保存属性列表时发生I / O错误,此方法不会抛出IOException。 保存属性列表的store(OutputStream out, String comments)方法是通过store(OutputStream out, String comments)方法或storeToXML(OutputStream os, String comment)方法。
    ObjectsetProperty(String key, String value) 致电 Hashtable方法 put
    voidstore(OutputStream out, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法加载到 Properties表中的格式输出流。
    voidstore(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式输出到输出字符流。
    voidstoreToXML(OutputStream os, String comment) 发出表示此表中包含的所有属性的XML文档。
    voidstoreToXML(OutputStream os, String comment, String encoding) 使用指定的编码发出表示此表中包含的所有属性的XML文档。
    SetstringPropertyNames() 返回此属性列表中的一组键,其中键及其对应的值为字符串,包括默认属性列表中的不同键,如果尚未从主属性列表中找到相同名称的键。

    这里我们简单使用下:

    public class PropertiesTest {
        public static void main(String[] args) throws IOException {
            Properties properties = new Properties();
            properties.setProperty("name","学习日记");
            properties.setProperty("age","18");
            System.out.println(properties);
    
            Set<String> strings = properties.stringPropertyNames();
            strings.forEach((e)->{
                System.out.println(e);
            });
    
            // 还可以和打印流结合使用
            PrintWriter pw = new PrintWriter("E:\\hello.txt");
            properties.list(pw);
            pw.close();
            System.out.println("properties持久化成功");
    
            // 还可以通过Store方法保存
            FileOutputStream fos = new FileOutputStream("E:\\hello.properties");
            properties.store(fos,"这是一个注释");
            fos.close();
    
            // 还有可以加载文件的load方法
            Properties properties1 = new Properties();
            FileInputStream fis = new FileInputStream("E:\\hello.properties");
            properties1.load(fis);
            fis.close();
            System.out.println(properties1);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    在这里插入图片描述

    在这里插入图片描述

    小结

    都看到这里了还不点个关注三连吗,后面我们还会学习java Nio Bio等,bye~

  • 相关阅读:
    掩码,反掩码与通配符掩码
    Ubuntu 20.04 for MacBook with T2 (Kernel 5.15, 5.16 & 5.17)
    Mac系统,webots和pycharm联合仿真,配置问题解决方案!
    Springboot+vue的人事管理系统(有报告),Javaee项目,springboot vue前后端分离项目。
    【计算机网络】计算机网络复习总结 ------ 物理层
    Git基础操作及协作流程
    开源游戏服务器框架NoahGameFrame(NF)客户端的Log日志系统(五)
    9. 回文数 --力扣 --JAVA
    ConvNext模型复现--CVPR2022
    Clickhouse 消除由group by产生的间隙
  • 原文地址:https://blog.csdn.net/hello_list/article/details/126662936