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,下载时间都不会有任何差别
下载速度通常受到网络的限制。例如:
- 最慢链路的原始数据速率
- 端到端网络延迟
- 整个路由上的拥塞量(影响数据包被丢弃的机会)
- 缺少其他因素(例如路由不稳定、链路/硬件不可靠、“成形”)
在您(IMO)浪费更多时间之前,我建议您实现下载代码“简单方法”。然后对其进行基准测试/评测(通过实际下载),以确定性能瓶颈是在代码中还是(正如我所怀疑的)在“网络”中。只有当您的测量结果表明优化代码是值得的时,才进行优化
更新-我刚刚注意到,在您的原始版本中,您一次读取一个字节的数据(使用
read()
从一个无缓冲的输入流中读取数据)。这肯定是低效的,并且可能会影响下载速度。如果您要从一个流中读取(或写入流),则需要将数据分成小块(例如,一次一个字节),然后应使用相应的缓冲流将其包装;例如,BufferedInputStream
,BufferedOutputStream
,BufferedReader
,BufferedWriter
使用缓冲流与非缓冲流(对于较小的I/O操作)之间的性能差异比经典流与NIO之间的差异大几个数量级
下载没有缓冲区的文件:Nio比io快
无论您使用的是经典I/O流还是NIOAPI,下载时间都不会有任何差别
下载速度通常受到网络的限制。例如:
- 最慢链路的原始数据速率
- 端到端网络延迟
- 整个路由上的拥塞量(影响数据包被丢弃的机会)
- 缺少其他因素(例如路由不稳定、链路/硬件不可靠、“成形”)
在您(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());