Java 一行行读大文件,读的过程中删除文件,竟然还能继续读剩下的?

2023-04-26 12:37:52 +08:00
 albin504
package io;

import java.io.*;
import java.util.concurrent.TimeUnit;

public class InodeTest {
    public static void main(String[] args) throws IOException, InterruptedException {
        BufferedReader reader = new BufferedReader(new FileReader("/Downloads/2020.zip"), 2);
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
            TimeUnit.MILLISECONDS.sleep(10);
        }
    }
}

这个文件有几百兆,程序执行一会儿,我删除 2020.zip 这个文件(从回收站也删了),竟然还能继续读到剩下的文件,为什么?

难道 java 一次性把文件内容都加载到进程中了吗?

3632 次点击
所在节点    Java
26 条回复
zjsxwc
2023-04-26 12:39:46 +08:00
文件系统了解下
pluto1
2023-04-26 12:47:12 +08:00
你看看文件系统剩余空间,应该是没释放的,因为还有 fd 没关掉,其实这时候底层的数据是还在的,等所有 fd 全部关了才会释放
zjp
2023-04-26 12:47:18 +08:00
看文件路径应该是 Linux ,只有在所有打开此文件的进程都关闭此文件后,文件才会实际删除
https://zhuanlan.zhihu.com/p/25650525
chenzhongxiang
2023-04-26 12:48:04 +08:00
win 应该删不掉,提示文件被占用。linux 能出现你描述的现象。不过在你删的是你看到的一个“快捷方式”。不过 zip 文件怎么一行一行的读? zip 是二进制文件。
documentzhangx66
2023-04-26 13:30:27 +08:00
建议楼主,有时间,先把计算机基础知识学一下。

不然,零基础学 Java ,就算再努力,也可能变成 CURD Boy 。
moyechen
2023-04-26 13:44:08 +08:00
你用 echo > /Downloads/2020.zip 应该就不能继续读了😄
msg7086
2023-04-26 13:44:48 +08:00
删除文件不影响文件内的数据,除非是粉碎文件。
bugmakerxs
2023-04-26 13:52:12 +08:00
句柄还在,占用的空间不会被释放。
RollingTruck
2023-04-26 13:55:19 +08:00
windows 下试了下, 中间应该有一层读缓存,
在 bufferedReader 读取到第一行后, 手动修改文件内第三行的内容,
使 bufferedReader 继续读取, 读取到第三行时, 仍旧读取到了修改前的内容
OpenJdk
2023-04-26 13:57:21 +08:00
不会一次加载到内存里面,应该是更文件系统有关。
RollingTruck
2023-04-26 13:59:23 +08:00
```java
try {
Scanner sc = new Scanner(System.in);
BufferedReader fileReader = new BufferedReader(new FileReader("path to file"));
System.out.println(fileReader.readLine());
sc.nextLine();
System.out.println(fileReader.readLine());
sc.nextLine();
System.out.println(fileReader.readLine());
sc.nextLine();
System.out.println(fileReader.readLine());
sc.nextLine();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

```
hez2010
2023-04-26 14:06:38 +08:00
你用的是 BufferedReader ,之所以叫做 Buffered 就是因为提前会对一部分或者全部内容做缓冲啊。
optional
2023-04-26 14:13:09 +08:00
linux 的文件机制。
churchmice
2023-04-26 14:29:14 +08:00
linux 下面把 shell bang 改成
#!/bin/rm
可以起到既删除文件又继续运行里面命令的效果,真乃杀人越货,居家旅行的必备良药
Worldispow
2023-04-26 14:43:26 +08:00
不但能继续读,记得还有个 lsof 还是命令,还能把文件找回
albin504
2023-04-26 14:52:30 +08:00
非常感谢。

unlink() deletes a name from the filesystem. If that name was
the last link to a file and no processes have the file open, the
file is deleted and the space it was using is made available for
reuse.

If the name was the last link to a file but any processes still
have the file open, the file will remain in existence until the
last file descriptor referring to it is closed.

删除一个文件时,如果有进程打开了该文件,文件实际上并不会删除,直到该文件相关的描述符都关了
albin504
2023-04-26 14:53:51 +08:00
@hez2010 Buffer size 设置的很小。2 字节
albin504
2023-04-26 14:54:46 +08:00
@moyechen 测试了,还能继续读
albin504
2023-04-26 14:56:11 +08:00
@pluto1 正解。感谢
liudaolunhuibl
2023-04-26 15:05:53 +08:00
new FileReader 会获取到一个文件描述符,fd ,文件被申请到了 fd 说明正在被正在运行的进程使用,而 linux 和 Uninx 中如果文件正在被使用了即使运行了 rm 也不会真正被删除:
https://access.redhat.com/solutions/2316

https://stackoverflow.com/questions/71198721/bufferedreader-still-reads-from-a-file-even-after-the-file-have-been-deleted

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/935599

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX