最初,我们在Java中使用FileOutputStream来创建一个简单地将数据导入文件的OutputStream。
因为Java7,我们也可以调用Files.newOutputStream,它为我们创建了一个行为完全相同的流(除了“构造函数”-arguments中的细微差别外)。
至少在OpenJDK 8中,旧的FileOutputStream的写方法被实现为本机方法,而Files.newOutputStream创建的OutputStream创建了一个ByteChannel,然后由委托给ByteChannel的OutputStream包装。
第二种方法读起来非常复杂,所有的包装器都是要写的调用经过的。一些幼稚的性能测试显示,新方法的速度稍微快了一点,但这并不是很重要,也几乎不值得提及。但也许我不是在挑选最好的用例。
在OpenJDK中新的基于ByteChannel的实现背后的理由是什么?是速度吗?在某些情况下,这会明显地加快速度吗?为什么?
(我知道这是依赖于JRE的,不应该依赖于确切的实现。这主要是对背景的好奇)。
发布于 2016-02-19 16:02:21
而由Files.newOutputStream创建的Files.newOutputStream创建了一个ByteChannel,然后由委托给ByteChannel的OutputStream包装。
THis并不总是正确的。这取决于FileSystem实现!或者,更准确地说,在FileSystemProvider实现上。
默认的实现实际上是这样的(注意:不是OpenJDK,而是Oracle的8u75,非常接近):
public OutputStream newOutputStream(Path path, OpenOption... options)
throws IOException
{
int len = options.length;
Set<OpenOption> opts = new HashSet<OpenOption>(len + 3);
if (len == 0) {
opts.add(StandardOpenOption.CREATE);
opts.add(StandardOpenOption.TRUNCATE_EXISTING);
} else {
for (OpenOption opt: options) {
if (opt == StandardOpenOption.READ)
throw new IllegalArgumentException("READ not allowed");
opts.add(opt);
}
}
opts.add(StandardOpenOption.WRITE);
return Channels.newOutputStream(newByteChannel(path, opts));
}但不必是这样的。
另一个FileSystemProvider实现可能很好地选择直接返回一个OutputStream,并使用例如Channels.newChannel()包装.newByteChannel()调用。
所以,答案确实是:这取决于。但是OpenJDK的家伙不是初学者,如果他们做出了这样的选择,他们有一个很好的理由。
是的,他们确实做了性能测试:p
例如:我在Dropbox上有一个JSR 203实现(虽然代码很旧);在这个实现中,FileSystemProvider为.newOutputStream()调用了这种方法。事实上,.newByteChannel()甚至不受支持(不过,在与nio-dev的专家交谈之后,这似乎是一个bug;但是文档没有提到需要实现)。
https://stackoverflow.com/questions/35509087
复制相似问题