Java-IO

简介: Java-IO

Java-IO

IO:I,Input(in)。O,Output(out)。Stream,流转。

数据流处理

数据流:数据+流(转)+处理

图解数据流:

image-20230112184059488

关于Stream:

image-20230112184147790

在IO中,IN和OUT是有阀门的,打开时才进行传输:

image-20230112184256528

文件流

image-20230112220958009

File file = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt");
System.out.println(file);// D:\Do_it\java\new\demo1\data\test.txt

判断是否为文件,注意这里是File对象是关联的文件或者文件夹

File file = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt");
File file1 = new File("D:\\Do_it\\java\\new\\demo1\\data");

System.out.println(file.isFile());// true
System.out.println(file1.isFile());// false

判断是否为文件夹

File file = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt");
File file1 = new File("D:\\Do_it\\java\\new\\demo1\\data");

System.out.println(file.isDirectory());// false
System.out.println(file1.isDirectory());// true

判断File对象是否存在关联(是否有这个路径)

File file = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt");
File file1 = new File("D:\\Do_it\\java\\new\\demo1\\node");

System.out.println(file.exists());// true
System.out.println(file1.exists());// false

文件流的常用方法:

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

public class Demo_01 {
    public static void main(String[] args) throws IOException {
        File file = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt");

        getFileAbout(file);
//        文件对象存在关联
//        文件名为:test.txt
//        文件绝对路径为:D:\Do_it\java\new\demo1\data\test.txt
//        文件长度为:5
//        文件最后修改时间为:1673529597503
    }

    public static void getFileAbout(File file, String... fileOrDir) throws IOException {
        if (file.exists()) {
            System.out.println("文件对象存在关联");
            if (file.isFile()) {
                System.out.println("文件名为:" + file.getName());
                System.out.println("文件绝对路径为:" + file.getAbsolutePath());
                System.out.println("文件长度为:" + file.length());
                System.out.println("文件最后修改时间为:" + file.lastModified());
                return;
            }
            if (file.isDirectory()) {
                System.out.println("文件夹名为:" + file.getName());
                System.out.println("文件夹绝对路径为:" + file.getAbsolutePath());
                System.out.println("文件夹最后修改时间为:" + file.lastModified());

                String[] list = file.list();
                System.out.println("文件夹下目录为:" + list);
                for (String s : list) {
                    System.out.println(s);
                }
                return;
            }
        }

        System.out.println("文件/文件夹路径不存在,开始创建");
        file.mkdirs();// 创建文件夹
        file.createNewFile();// 创建文件
    }
}

复制文件:

import java.io.*;

public class Demo_02 {
    public static void main(String[] args) {
        // TODO 原文件
        File srcFile = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt");
        // TODO 复制的文件(自动创建)
        File destFile = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt.copy");

        // TODO 文件输入流(管道对象)
        FileInputStream in = null;
        // TODO 文件输出流(管道对象)
        FileOutputStream out = null;

        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(destFile);
            
            int data;
            // TODO 打卡阀门,流转数据(输入)。(打开一次关闭一次,所以用循环。当没有数据后读取-1)
            while ((data = in.read()) != -1) {
                // TODO 打卡阀门,流转数据(输出)
                out.write(data);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

缓冲流

建立一个缓冲区,使其输入输出的阀门都只开一次。

image-20230112225352373

读取的时候读取缓冲区的数据,写的时候也是。

import java.io.*;

public class Demo_03 {
    public static void main(String[] args) {
        // TODO 原文件
        File srcFile = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt");
        // TODO 复制的文件(自动创建)
        File destFile = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt.copy");

        // TODO 文件输入流(管道对象)
        FileInputStream in = null;
        // TODO 文件输出流(管道对象)
        FileOutputStream out = null;

        // TODO 缓冲输入流(管道对象)
        BufferedInputStream bufferIn = null;
        // TODO 缓冲输出流(管道对象)
        BufferedOutputStream bufferOut = null;
        // TODO 缓冲区
        byte[] cache = new byte[1024];


        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(destFile);

            bufferIn = new BufferedInputStream(in);
            bufferOut = new BufferedOutputStream(out);

            int data;
            // TODO 打卡阀门,流转数据(输入)。(打开一次关闭一次,所以用循环。当没有数据后读取-1)
            while ((data = bufferIn.read(cache)) != -1) {
                // TODO 打卡阀门,流转数据(输出)
                bufferOut.write(cache, 0, data);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (bufferIn != null) {
                try {
                    bufferIn.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (bufferOut != null) {
                try {
                    bufferOut.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

字符流

之前都是流转字节(byte),非常不方便。我们将流转的数据转为字符:

字符流中,一行一行的进行流转。

import java.io.*;

public class Demo_04 {
    public static void main(String[] args) {
        // TODO 原文件
        File srcFile = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt");
        // TODO 复制的文件(自动创建)
        File destFile = new File("D:\\Do_it\\java\\new\\demo1\\data\\test.txt.copy");

        // TODO 文件输入流(管道对象)
        FileInputStream in = null;
        // TODO 文件输出流(管道对象)
        FileOutputStream out = null;

        // TODO 字符输入流(管道对象)
        BufferedReader reader = null;
        // TODO 字符输出流(管道对象)
        PrintWriter writer = null;

        try {
            reader = new BufferedReader(new FileReader(srcFile));
            writer = new PrintWriter(destFile);

            String line = null;

            // TODO 打卡阀门,流转数据(输入)。(打开一次关闭一次,所以用循环。当没有字符串返回null)
            while ((line = reader.readLine()) != null) {
                // TODO 打卡阀门,流转数据(输出)
                writer.println(line);
                System.out.println(line);
            }
            // hello
            // nice demo!
            writer.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (writer != null) {
                writer.close();
            }
        }
    }
}

序列化与反序列化

我们之前将字符串进行流转,那么对象是否也可以呢?我们如何将程序中的对象写入文件呢?

image-20230112233234676image-20230112233324210

在java中,我们将对象变成字节写入文件,这个过程叫序列化过程。而将文件中的数据读成对象叫反序列化

序列化

需要对象的类实现Serializable接口(可序列化的)

package chapter08;

import java.io.*;

public class Demo_05 {
    public static void main(String[] args) {
        // TODO 数据文件对象
        File dateFile = new File("D:\\Do_it\\java\\new\\demo1\\data\\obj.dat");

        // TODO 对象输出流(管道对象)
        ObjectOutputStream objectOutput = null;
        FileOutputStream out = null;


        try {
            out = new FileOutputStream(dateFile);
            objectOutput = new ObjectOutputStream(out);
            User user = new User();
            
            objectOutput.writeObject(user);

            objectOutput.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (objectOutput != null) {
                try {
                    objectOutput.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

class User implements Serializable {
}

这时候已经将对象写入了文件。

反序列化

import java.io.*;

public class Demo_05 {
    public static void main(String[] args) {
        // TODO 数据文件对象
        File dateFile = new File("D:\\Do_it\\java\\new\\demo1\\data\\obj.dat");

        // TODO 对象输出流(管道对象)
        ObjectInputStream objectIn = null;
        FileInputStream in = null;


        try {
            in = new FileInputStream(dateFile);
            objectIn = new ObjectInputStream(in);
            Object o = objectIn.readObject();
            System.out.println(o);// chapter08.User@1cf4f579
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

class User implements Serializable {
}

常见异常

在使用FileInputStream创建文件输入对象时,可能会出现FileNotFoundException,文件未找到的异常。

FileInputStream input = new FileInputStream("xxx");// 异常: java.io.FileNotFoundException

所以我们通常采用这样的套路:

FileInputStream input = null;
try {
    input = new FileInputStream("xxx");
} catch (FileNotFoundException e) {
    throw new RuntimeException(e);
} finally {
    try {
        if (input != null) {
            input.close();
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

其中,我们将input对象初始化为null,并且在try/catch语句中尝试使用new FileInputStream来时对象指向它的实例。

然后再进行对FileNotFoundException异常的捕捉。

由于流对象会占资源,所以我们最后要将这个管道进行关闭。而这里也需要对IOException异常进行捕捉。

对于ObjectInputStream类可能出现ClassNotFoundException,这是因为程序不知道该段程序中是否有这个对象的类,如果没有则会抛出异常。

ObjectInputStream objectInput = null;
try {
    objectInput.readObject();
} catch (IOException e) {
    throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
    throw new RuntimeException(e);
}

对于ObjectOutputStream类可能会出现NotSerializableException异常,这是因为我们在序列化时应该允许序列化,如果不允许则会抛出异常。(需要对象的类实现Serializable接口)

详细代码见:序列化

相关文章
MFC编程 -- 实现拖拽文件获取路径
MFC编程 -- 实现拖拽文件获取路径
327 0
|
存储 Kubernetes 负载均衡
K8S原理和实践
K8S原理和实践
459 0
|
存储 移动开发 前端开发
2023年最新前端面试题汇总大全(含答案超详细,HTML,JS,CSS汇总篇)-- 持续更新6
2023年最新前端面试题汇总大全(含答案超详细,HTML,JS,CSS汇总篇)-- 持续更新
496 0
|
11月前
|
存储 运维 Prometheus
都有什么报警监控工具
都有什么报警监控工具
236 1
|
12月前
|
人工智能 Unix 人机交互
揭秘操作系统:从命令行到图形界面的演变之旅
【10月更文挑战第3天】本文将带你穿越时空,探索操作系统从简单的命令行界面(CLI)如何进化为今天广泛使用的图形用户界面(GUI)。我们将一探究竟,了解这一变革背后的故事和技术进步,同时通过代码示例,揭示现代操作系统如何实现这一转换。文章不仅回顾了历史,还展望了未来可能的技术革新,旨在激励读者思考操作系统设计的哲学和未来发展方向。
255 4
|
XML SQL Java
MyBatis 的延迟加载是如何实现的
MyBatis的延迟加载(懒加载)特性提高了性能,只在需要时加载关联数据。配置延迟加载需在`mybatis-config.xml`中设置`lazyLoadingEnabled`为`true`,`aggressiveLazyLoading`为`false`。实现原理基于代理对象,MyBatis为延迟加载属性创建代理,在访问时触发实际查询。代理通过Java动态代理实现,拦截方法调用,按需加载数据。
400 0
|
移动开发 JavaScript 前端开发
学习vue3使用在线官方开发环境play.vuejs.org进行测试
学习vue3使用在线官方开发环境play.vuejs.org进行测试
244 1
|
缓存 Unix 编译器
Cmake 的构建结构:理解 Cmake 的构建过程和依赖管理
Cmake 的构建结构:理解 Cmake 的构建过程和依赖管理
301 0
|
存储 消息中间件 缓存
Redis分片集群的探讨
随着互联网应用的发展和数据量的不断增长,单机的Redis已经无法满足高并发和大规模数据存储的需求。为了解决这个问题,Redis引入了分片集群的概念。本文将探讨Redis分片集群的原理、实现方式以及相关的注意事项。
437 0
|
安全 搜索推荐 Java
【SpringSecurity6.x】会话管理
【SpringSecurity6.x】会话管理
276 0