"The reason is that on Linux, you can delete a file from a directory even if the file is open (assuming appropriate permissions). This is not possible under Windows. This information is sourced from
sun.nio.fs.UnixChannelFactory. If the 'delete on close' flag is set, the file will be unlinked immediately. However, it should be noted that the specification acknowledges that an implementation cannot guarantee to unlink the correct file when replaced by an attacker after it is opened. If you modify your code as suggested..."
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)
编辑 如果您只想确保在应用程序退出时删除临时文件,请查看下面的代码片段。
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
- 使用
DELETE_ON_CLOSE
打开 OutputStream
按照这个顺序进行操作,它将按照您的预期工作。
以下是有效的代码片段。
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
而不是断点)。你在哪个操作系统上运行? - Jon SkeetDELETE_ON_CLOSE
,那么在OSX上它可以正常工作。 - MaxDELETE_ON_CLOSE
文档确实指出:“关于何时以及如何删除文件的许多细节是实现特定的,因此未予规定。” - Jonny Henly