【问题标题】:Download a file without buffer: Nio is faster than io?下载没有缓冲的文件:Nio 比 io 快?
【发布时间】:2014-08-10 01:09:11
【问题描述】:

我正在为我的项目开发更新程序,我想快速下载文件。 每次更新,都会有一些文件大小不同。所以我认为我不需要缓冲区,或者肯定没有定义。我已经这么写了:

File file = new File..
InputStream input = new InputStream...
OutputStream output = new OutputStream(..).write(input.read());

这个运行完美!但我的朋友对我说; “嘿,我们从 jdk7 获得了 FileChannel”。 然后我考虑了一下,但是我们不能在没有 ByteBuffer 的情况下创建和导入数据到 FileChannel。

FileChannel channel = new FileOutputStream(file).getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(..);
buffer.putInt(inputstream.read());

channel.write(buffer);

那么更快的是什么?更好的 ?谢谢!

更新:(我认为最好的解决方案,非常快)

URLConnection connection = new URL(url).openConnection();

File file = new File(connection.getURL().getPath().substring(1));
if (file.getParentFile() != null)
    file.getParentFile().mkdirs();

FileChannel output = new FileOutputStream(file).getChannel();
output.transferFrom(Channels.newChannel(connection.getInputStream()), 0, connection.getContentLengthLong());

有效!

【问题讨论】:

  • 它适用于您尝试过的东西。一般来说,transferFrom/To() 不能保证在一次调用中完成整个传输。这就是他们返回计数的原因。你必须循环。
  • 为什么?没有解释
  • 新:我尝试下载 2GB,它确实有效!下载没有中断
  • 如何在控制器中使用它来响应?

标签: java io nio


【解决方案1】:

下载没有缓冲的文件:Nio 比 io 快?

无论您使用传统 I/O 流还是 NIO API,下载时间都不太可能

下载速度通常受网络限制。比如:

  • 最慢链路的原始数据速率,
  • 端到端网络延迟,
  • 整个路由的拥塞量(这会影响数据包被丢弃的可能性),
  • 没有其他因素(例如路由不稳定、不可靠的链接/硬件、“整形”)。

然后,“另一端”能否以“网络”能够承载的速率提供(或消费)数据。这通常取决于磁盘和网络 I/O 带宽以及另一端的负载。

一般来说,您的客户端将数据从内存缓冲区移动到本地目标文件的能力不是问题。


在您(IMO)在此浪费更多时间之前,我建议您“以简单的方式”实现下载代码。然后对其进行基准测试/分析(通过实际下载)以确定性能瓶颈是在代码中还是(我怀疑)在“网络”中。只有当您的测量结果表明它可能值得时,才去努力优化您的代码。


更新 - 我刚刚注意到,在您的原始版本中,您一次读取一个字节的数据(使用来自无缓冲输入流的read()。这肯定效率低下,并且可能会影响下载速度。如果您要以小块(例如一次一个字节)从流中读取(或写入流),那么您应该用相应的缓冲流;例如BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter

使用缓冲流与非缓冲流(对于小型 I/O 操作)之间的性能差异数量级比经典流与 NIO 之间的差异更大。

【讨论】:

  • @Romain-p - 是的......但请注意 EJP 富有洞察力的评论!
猜你喜欢
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 2013-12-01
  • 2014-09-12
  • 1970-01-01
  • 2021-08-17
  • 2010-11-29
相关资源
最近更新 更多