我有以下代码:
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import static java.nio.file.StandardOpenOption.CREATE_NEW;
import static java.nio.file.StandardOpenOption.DELETE_ON_CLOSE;
public class Test {
public static void main(String[] args) throws IOException {
try (OutputStream outputStream = Files.newOutputStream(Paths.get("test"), CREATE_NEW, DELETE_ON_CLOSE)) {
outputStream.write(123);
outputStream.flush();
System.out.println("done");
}
}
}
我在调用System.out.println
时设置了一个断点,并检查了我的工作目录。没有名为test
的文件。为什么输出流没有写入文件?
答案 0 :(得分:3)
原因是在Linux上,即使文件处于打开状态,您也可以从目录中删除文件(这里默认使用适当的权限)。在Windows下,这是不可能的。
来自sun.nio.fs.UnixChannelFactory
的来源//如果在关闭时删除,则立即取消链接文件。规范很清楚 //实现无法保证在执行时取消链接正确的文件 //在打开后被攻击者替换 if(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)
编辑如果您只想确保在您的应用程序退出时删除临时文件,请查看下面的代码段。
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