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

Java 下载没有缓冲区的文件:Nio比io快?,java,io,nio,Java,Io,Nio,我正在为我的项目开发一个更新程序,我想快速下载文件。 每次更新,都会有一些大小不同的文件。所以我认为我不需要缓冲区,或者肯定不需要定义缓冲区。我写了这么多: File file = new File.. InputStream input = new InputStream... OutputStream output = new OutputStream(..).write(input.read()); 这个跑得很好!但是我的朋友对我说;“嘿,我们从jdk7获得了FileChannel”。

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

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);
那么什么更快呢?更好?谢谢大家!

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

它起作用了

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

无论您使用的是经典I/O流还是NIOAPI,下载时间都不会有任何差别

下载速度通常受到网络的限制。例如:

  • 最慢链路的原始数据速率
  • 端到端网络延迟
  • 整个路由上的拥塞量(影响数据包被丢弃的机会)
  • 缺少其他因素(例如路由不稳定、链路/硬件不可靠、“成形”)
然后,问题是“另一端”是否能够以“网络”能够承载的速率提供(或消费)数据。这通常取决于另一端的磁盘和网络I/O带宽和负载

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


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


更新-我刚刚注意到,在您的原始版本中,您一次读取一个字节的数据(使用
read()
从一个无缓冲的输入流中读取数据)。这肯定是低效的,并且可能会影响下载速度。如果您要从一个流中读取(或写入流),则需要将数据分成小块(例如,一次一个字节),然后应使用相应的缓冲流将其包装;例如,
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter

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

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

无论您使用的是经典I/O流还是NIOAPI,下载时间都不会有任何差别

下载速度通常受到网络的限制。例如:

  • 最慢链路的原始数据速率
  • 端到端网络延迟
  • 整个路由上的拥塞量(影响数据包被丢弃的机会)
  • 缺少其他因素(例如路由不稳定、链路/硬件不可靠、“成形”)
然后,问题是“另一端”是否能够以“网络”能够承载的速率提供(或消费)数据。这通常取决于另一端的磁盘和网络I/O带宽和负载

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


在您(IMO)在这方面浪费更多时间之前,我建议您实现下载代码“简单方式”。然后对其进行基准测试/评测(使用真实下载),以确定性能瓶颈是在代码中还是(如我所怀疑的)在“网络”中。只有当您的测量结果表明优化代码是值得的时,才进行优化


更新-我刚刚注意到,在您的原始版本中,您一次读取一个字节的数据(使用
read()
从一个无缓冲的输入流中读取数据)。这肯定是低效的,并且可能会影响下载速度。如果您要从一个流中读取(或写入流),则需要将数据分成小块(例如,一次一个字节),然后应使用相应的缓冲流将其包装;例如,
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter


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

它适用于您尝试过的内容。一般来说,transferFrom/To()不能保证在一次调用中完成整个传输。这就是他们返回计数的原因。你必须循环。为什么?没有解释新的:我尝试下载2GB,它确实有效!下载没有中断。如何在控制器中使用此响应?它适用于你尝试过的内容。一般来说,transferFrom/to()不能保证在一次呼叫中完成整个传输。这就是他们返回计数的原因。你必须循环。为什么?没有解释新的:我尝试下载2GB,它确实有效!下载没有中断。如何使用此命令在控制器中响应?@Romain-p-是…但请注意EJP的深刻评论!@Romain-p-是…但请注意EJP的见解这是一个令人讨厌的评论!
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());