原因是,在Linux上,即使文件已打開,也可以從目錄中刪除文件(適當的權限在此默默承擔)。在Windows下,這是不可能的。
從sun.nio.fs.UnixChannelFactory
//源立即斷開鏈接文件,如果在關閉刪除。該規範明確指出:
//當攻擊者打開後,攻擊者可以用
代替執行程序。
如果(flags.deleteOnClose){ ...
如果你作爲
for (int i = 0; i < 10; i++) {
outputStream.write(123);
outputStream.flush();
System.out.println("flush...");
Thread.sleep(10_000);
}
你都能夠看到該文件是開放的,但已經刪除
# assumed that the code write to Paths.get("/tmp/test")
lsof | grep "/tmp/test"
... /tmp/test (deleted)
修改代碼
編輯如果您只想確保在應用程序退出時刪除臨時文件,請查看sn下面的ippet。
import java.io.File;
import java.io.OutputStream;
import java.nio.file.Files;
import static java.nio.file.StandardOpenOption.CREATE_NEW;
public class Main {
public static void main(String[] args) throws Exception {
File file = new File("/tmp/test");
file.deleteOnExit();
System.out.println("tempFile = " + tempFile);
try (OutputStream outputStream = Files.newOutputStream(file.toPath(),
CREATE_NEW)) {
outputStream.write(123);
outputStream.flush();
System.out.println("done");
}
System.out.printf("%s exists: %s%n", file, file.exists());
}
}
文件/tmp/test
將在應用程序完成時被刪除。
輸出(文件此時仍然存在)
/tmp/test exists: true
,如果你現在的控制檯
$ ls /tmp/test
ls: cannot access '/tmp/test': No such file or directory
對檢查如果你甚至不關心你可能會考慮的文件名使用隨機生成的一個。
File tempFile = File.createTempFile("foo_", ".tmp", new File("/tmp"));
編輯另一種解決辦法是。
- 創建文件(喜歡使用一個隨機的臨時文件名)
- 打開
InputStream
- 打開
OutputStream
與DELETE_ON_CLOSE
的順序做它,你期望它會工作。
查找以下工作片段。
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardOpenOption.APPEND;
import static java.nio.file.StandardOpenOption.DELETE_ON_CLOSE;
import static java.nio.file.StandardOpenOption.READ;
public class DeleteOnClose {
public static void main(String[] args) throws IOException {
Path path = Paths.get("/tmp/test");
System.out.println("before create: " + Files.exists(path));
Files.createFile(path);
System.out.println("after create: " + Files.exists(path));
try (InputStream in = Files.newInputStream(path, READ);
OutputStream out = Files.newOutputStream(path, APPEND,
DELETE_ON_CLOSE)) {
out.write("Hello file!".getBytes(UTF_8));
out.flush();
for (int c = in.read(); c >= 0; c = in.read()) {
System.out.print((char) c);
}
System.out.println();
}
System.out.println("after close: " + Files.exists(path));
}
}
輸出
before create: false
after create: true
Hello file!
after close: false
嗯......對我的作品(使用'Thread.sleep'而不是斷點)。你在運行什麼操作系統? –
OSX。如果我刪除'DELETE_ON_CLOSE',它對我也有用。 – Max
我認爲發生的事情是基於Unix的操作系統立即刪除該文件,因爲具有打開文件句柄的已刪除文件仍然可以被訪問。雖然這似乎違反了API。 – Max