前言(废话🤪,不用看)

学习项目的过程中,我觉得自己有点太急功近利了一直跟着视频敲没有自己的思考(主要是最近在牛客读到了一位大佬👍👍👍,程序员牛肉的文章),🙌学技术不是一味的复制粘贴,特别是做项目,要边学边思考,一个功能的实现,我学会了什么技术,还有没有更好的可以替代它。

之前学的基础知识其实也没有学完,像集合,线程… 都还不知道是啥就开始学JavaWeb做项目了,在项目中使用队列存储我都一脸懵,在这里以问题的形式写一个学习笔记🤔,不仅仅是复习,也为以后的面试做准备,还有还有我的刷题网站是面试鸭呦🦆🦆🦆

JavaIO基础😎

📚IO 即 Input/Output,输入和输出。数据输入到计算机内存的过程即输入,反之输出到外部存储(比如数据库,文件,远程主机)的过程即输出。

流的分类(IO 流有40 多个类,但都是从这几个基类中派生出来的):

类型常见类
输入流(所有输入流基类)InputStream(字节输入流), Reader(字符输入流)
输出流(所有输出流基类)OutputStream(字节输出流), Writer(字符输出流)

🧐下面来看看几个简单的代码,简单介一下常用的与文件相关的方法:

1. InputStream(字节输入流):

InputStream 常用方法:

  • read():返回输入流中下一个字节的数据。返回的值介于 0 到 255 之间。如果未读取任何字节,则代码返回 -1 ,表示文件结束。
  • readAllBytes():读取输入流中的所有字节,返回字节数组
  • close():关闭输入流释放相关的系统资源。

FileInputStream 是一个比较常用的字节输入流对象,可直接指定文件路径,可以直接读取单字节数据,也可以读取至字节数组中。

FileInputStream 代码示例:

//读取文件
FileInputStream fis = new FileInputStream("input.txt");
int data;
while ((data = fis.read()) != -1) {  // 每次读一个字节
    System.out.print((char) data);   // 转成字符输出
}
fis.close();

2. OutputStream(字节输出流)

OutputStream用于将数据(字节信息)写入到目的地(通常是文件),java.io.OutputStream抽象类是所有字节输出流的父类。

OutputStream 常用方法:

  • write(int b):将特定字节写入输出流
  • flush():刷新此输出流并强制写出所有缓冲的输出字节。
  • close():关闭输出流释放相关的系统资源。

FileOutputStream 是最常用的字节输出流对象,可直接指定文件路径,可以直接输出单字节数据,也可以输出指定的字节数组。

FileOutputStream 代码示例:

//写入文件
FileOutputStream fos = new FileOutputStream("output.txt");
String text = "Hello Java IO!";
fos.write(text.getBytes());  // 把字符串转成字节写入文件
fos.close();

3. Reader(字符输入流)

Reader用于从源头(通常是文件)读取数据(字符信息)到内存中,java.io.Reader抽象类是所有字符输入流的父类。

Reader 用于读取文本, InputStream 用于读取原始字节。

Reader 常用方法:

  • read() : 从输入流读取一个字符。
//读取文本
FileReader fr = new FileReader("input.txt");
int ch;
while ((ch = fr.read()) != -1) {
    System.out.print((char) ch);
}
fr.close();

4. Writer(字符输出流)

//写入文本
FileWriter fw = new FileWriter("output.txt");
fw.write("你好,Java IO!");
fw.close();

不过,一般我们是不会直接单独使用 FileInputStream (前面讲的这些),通常会配合 BufferedInputStream(字节缓冲输入/输出流)来使用。

就比如代码生成器(我自己写的) , 构建项目生成代码的时候里面就是这样写的:

 // 声明流变量(用于后续关闭)
        OutputStream out = null;
        OutputStreamWriter outw = null;
        BufferedWriter bw = null;//字节缓冲流
        try {
            // 3. 打开文件输出流(UTF-8 编码)
            out = new FileOutputStream(poFile);
            outw = new OutputStreamWriter(out,"utf8");
            bw = new BufferedWriter(outw);//字节缓冲流

字节缓冲流

IO 操作是很消耗性能的,缓冲流将数据加载至缓冲区,一次性读取/写入多个字节,从而避免频繁的 IO 操作,提高流的传输效率

🙌🙌🙌他就相当于一个装饰作用,用来装饰来增强 InputStream 和OutputStream子类对象的功能。

// 新建一个 BufferedInputStream 对象
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("input.txt"));

字节流和字节缓冲流的性能差别主要体现在我们使用两者的时候都是调用 write(int b) 和 read() 这两个一次只读取一个字节的方法的时候。由于字节缓冲流内部有缓冲区(字节数组),因此,字节缓冲流会先将读取到的字节存放在缓存区,大幅减少 IO 次数,提高读取效率。

File类

File 类是 Java 中用于表示文件和目录路径名的抽象,属于 java.io 包。它不直接操作文件内容(如读写),而是用于管理文件/目录的元信息和结构(如创建、删除、重命名、判断是否存在等)。

一、核心概念

  • File 对象代表一个路径(可能是文件,也可能是目录)。
  • 路径可以是绝对路径(如 /home/user/data.txt)或相对路径(如 ./config/app.properties)。
  • File 是平台无关的(Windows 的 \ 和 Linux 的 / 都能处理)。
  • 所有操作都是 “声明式” 的:new File(“a.txt”) 只是创建一个对象,并不会在磁盘上创建文件

二、常用构造方法

构造方法说明
File(String pathname)通过路径字符串创建 File 对象(最常用)
例:new File("logs/app.log")
File(String parent, String child)拼接父路径和子路径
例:new File("/home", "user.txt")/home/user.txt
File(File parent, String child)使用另一个 File 作为父目录
例:new File(new File("/tmp"), "data.db")

三、核心方法分类详解

1. 路径相关

方法返回值说明
String getPath()路径字符串返回构造时传入的原始路径
String getAbsolutePath()绝对路径返回该 File 的绝对路径(解析相对路径)
String getName()文件/目录名返回路径最后一部分
例:/a/b/c.txt"c.txt"
String getParent()父路径字符串返回父目录路径(若无则返回 null
File getParentFile()File 对象返回父目录的 File 对象(更安全)
File f = new File("src/main/java/App.java");
System.out.println(f.getName());        // App.java
System.out.println(f.getParent());      // src/main/java
System.out.println(f.getAbsolutePath()); // C:\project\src\main\java\App.java (Windows 示例)

2. 文件/目录状态判断

方法返回值说明
boolean exists()是否存在判断文件或目录是否存在(最常用!)
boolean isFile()是否为文件存在且是文件(不是目录)
boolean isDirectory()是否为目录存在且是目录
boolean canRead() / canWrite() / canExecute()权限检查判断当前用户是否有对应权限
long length()文件大小(字节)仅对文件有效,目录返回 0
File file = new File("data.txt");
if (file.exists()) {
    if (file.isFile()) {
        System.out.println("Size: " + file.length() + " bytes");
    }
}

3. 创建与删除

方法说明
boolean createNewFile()创建新文件(如果不存在)
⚠️ 若父目录不存在会抛 IOException
boolean mkdir()创建单级目录(父目录必须存在)
boolean mkdirs()递归创建多级目录(推荐!)
例:new File("a/b/c").mkdirs() 会创建 a → b → c
boolean delete()删除文件或空目录
⚠️ 不能删除非空目录!
void deleteOnExit()注册 JVM 退出时删除(用于临时文件)
File dir = new File("output/logs");
if (!dir.exists()) {
    dir.mkdirs(); // 安全创建多级目录
}

✨这里举个例子,主要是来看看JavaIO在具体项目中怎么用:

用它来实现文件上传最基本的功能,将接收到的文件保存在本地服务器的磁盘目录中了,客户端访问时可以显示出来
结合前端看看具体功能(提交姓名性别头像):

在这里插入图片描述

来看后端代码:

...
@Slf4j
@RestController
public class UploadController {

    private static final String UPLOAD_DIR = "D:/images/";
    /**
     * 上传文件 - 参数名file
     */
    @PostMapping("/upload")
    public Result upload(MultipartFile file) throws Exception {
        log.info("上传文件:{}, {}, {}", username, age, file);
        if (!file.isEmpty()) {
            // 生成唯一文件名(防止上传的文件名相同,后面上传的会覆盖前面文件)
            String originalFilename = file.getOriginalFilename();
            String extName = originalFilename.substring(originalFilename.lastIndexOf("."));
            String uniqueFileName = UUID.randomUUID().toString().replace("-", "") + extName;
            // 拼接完整的文件路径
            File targetFile = new File(UPLOAD_DIR + uniqueFileName);

            // 如果目标目录不存在,则创建它
            if (!targetFile.getParentFile().exists()) {
                targetFile.getParentFile().mkdirs();
            }
            // 保存文件
            file.transferTo(targetFile);
        }
        return Result.success();
    }
}

🙌其中有几个点不好理解(我让ai解释了一下):
1.MultipartFile:Spring中提供了一个API,使用这个API就可以来接收到上传的文件
String getOriginalFilename(); MultipartFile 常见方法,获取原始文件名

2.file.transferTo(…) InputStream 常用方法:作用是将上传的临时文件写入目标位置。

调用 transferTo() 方法后,Spring 会使用 Java I/O 流的方式将这个临时文件复制到指定的目标路径。
其本质是调用了类似下面的逻辑(真的很方便):


InputStream inputStream = file.getInputStream();
OutputStream outputStream = new FileOutputStream(targetFile);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
    outputStream.write(buffer, 0, bytesRead);
}

小白啊!!!写的不好轻喷啊🤯如果觉得写的不好,点个赞吧🤪(批评是我写作的动力)

…。。。。。。。。。。。…请添加图片描述

…。。。。。。。。。。。…

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐