互联网上有很多例子显示如何使用StandardOpenOption.DELETE_ON_CLOSE,例如:
Files.write(myTempFile, ..., StandardOpenOption.DELETE_ON_CLOSE);
其他示例同样使用Files.newOutputStream(..., StandardOpenOption.DELETE_ON_CLOSE)
。
我怀疑所有这些例子都可能存在缺陷。写文件的目的是让你在某个时候回读它;否则,为什么还要写呢?但是,在你有机会阅读文件之前,不会删除文件吗?
如果你创建一个工作文件(用于处理太大而无法留在内存中的大量数据),那么你就不会使用RandomAccessFile
代替读写访问权限?但是,就我所见,RandomAccessFile
并没有为您提供指定DELETE_ON_CLOSE的选项。
那么有人可以告诉我DELETE_ON_CLOSE 实际有用吗?
答案 0 :(得分:3)
首先,我同意你Files.write(myTempFile, ..., StandardOpenOption.DELETE_ON_CLOSE)
在这个例子中使用DELETE_ON_CLOSE是没有意义的。在通过互联网进行(不那么激烈)搜索之后,我能找到的唯一一个显示上述用法的例子是你可能得到它的那个(http://softwarecave.org/2014/02/05/create-temporary-files-and-directories-using-java-nio2/)。
此选项不仅适用于Files.write(...)
。 API制作非常明确:
此选项主要用于工作文件,它们仅由单个Java虚拟机实例使用。建议在打开其他实体同时打开的文件时,不建议使用此选项。
很抱歉,我不能给你一个有意义的简短例子,但是看到像操作系统使用的交换文件/分区这样的文件。如果当前JVM需要在光盘上临时存储数据,并且在关机后数据不再有用。作为实际例子,我会提到它类似于JEE应用程序服务器,它可能决定将某些实体序列化为光盘以释放内存。
编辑可能以下列(过度简化的代码)为例来说明原理。 (所以请:没有人应该开始讨论这个“数据管理”可能会有不同的做法,使用固定的临时文件名是坏的等等,...)
static final int RECORD_LENGTH = 20;
static final String RECORD_FORMAT = "%-" + RECORD_LENGTH + "s";
// add exception handling, left out only for the example
public static void main(String[] args) throws Exception {
EnumSet<StandardOpenOption> options = EnumSet.of(
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.READ,
StandardOpenOption.DELETE_ON_CLOSE
);
Path file = Paths.get("/tmp/enternal_data.tmp");
try (SeekableByteChannel sbc = Files.newByteChannel(file, options)) {
// during your business processing the below two cases might happen
// several times in random order
// example of huge datastructure to externalize
String[] sampleData = {"some", "huge", "datastructure"};
for (int i = 0; i < sampleData.length; i++) {
byte[] buffer = String.format(RECORD_FORMAT, sampleData[i])
.getBytes();
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
sbc.position(i * RECORD_LENGTH);
sbc.write(byteBuffer);
}
// example of processing which need the externalized data
Random random = new Random();
byte[] buffer = new byte[RECORD_LENGTH];
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
for (int i = 0; i < 10; i++) {
sbc.position(RECORD_LENGTH * random.nextInt(sampleData.length));
sbc.read(byteBuffer);
byteBuffer.flip();
System.out.printf("loop: %d %s%n", i, new String(buffer));
}
}
}
答案 1 :(得分:1)
DELETE_ON_CLOSE
适用于工作临时文件。
如果您需要进行一些需要临时存储在文件上的操作,但不需要使用当前执行之外的文件 DELETE_ON_CLOSE为此提供了一个很好的解决方案。
一个例子是当你需要存储无法在内存中保留的信息时,例如因为它们太重了。 另一个例子是,当你需要临时存储信息时,你只需要在一瞬间就需要它们而你不想为此占用记忆。
想象一下,一个过程需要大量时间才能完成的情况。您将信息存储在文件中,然后才能使用它们(可能在几分钟或几小时后)。如果您不需要,这可以保证您不会将内存用于这些信息。
DELETE_ON_CLOSE
尝试在显式关闭文件时调用方法close()
或者在JVM关闭之前删除文件(如果之前没有手动关闭)。
答案 2 :(得分:1)
以下是两种可能的使用方法:
此方法返回适合读取和写入的SeekableByteChannel,其中可以修改当前位置。
对于需要将某些数据存储在内存中以进行读/写访问而在应用程序关闭后不需要保留的情况,这似乎非常有用。
使用任意文本文件的示例:
Path p = Paths.get("C:\\test", "foo.txt");
System.out.println(Files.exists(p));
try {
Files.createFile(p);
System.out.println(Files.exists(p));
try (BufferedWriter out = Files.newBufferedWriter(p, Charset.defaultCharset(), StandardOpenOption.DELETE_ON_CLOSE)) {
out.append("Hello, World!");
out.flush();
try (BufferedReader in = Files.newBufferedReader(p, Charset.defaultCharset())) {
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println(Files.exists(p));
此输出(如预期):
false
true
Hello, World!
false
这个例子显然是微不足道的,但我想有很多情况下这种方法可能派上用场。
但是,我仍然认为旧的File.deleteOnExit
方法可能更好,因为您不需要在文件的任何读取操作期间保持输出流打开。