【问题标题】:Fast way to read file from input stream when we know the size with low memory usage当我们知道内存使用量低的大小时,从输入流中读取文件的快速方法
【发布时间】:2020-03-03 21:31:09
【问题描述】:

当我们知道数据的大小时,有没有更快的方法从输入流中读取? 我的这段代码很慢:

File file = new File("file.jar");

if(!file.exists)file.createNewFile();
String url = "https://launcher.mojang.com/v1/objects/3870888a6c3d349d3771a3e9d16c9bf5e076b908/client.jar";
int len = 8461484;

InputStream is = new URL(url).openStream();

if(!file.exists())
    file.createNewFile();

PrintWriter writer = new PrintWriter(file);

for(long i = 0;i < len;i ++) {
    writer.write(is.read());
    writer.flush();
    System.out.println(i);
}
writer.close();

【问题讨论】:

  • 不要逐字节读取。使用缓冲区。
  • 带缓冲阅读器?
  • 不过需要很多回忆
  • 另外,在每个write 之后显式刷新也无济于事。
  • Readers 和 Writers 用于文本文件。我看到您正在从 InputStream 中读取;你确定这是一个文本文件吗?您确定此文本文件与您的作者的文本格式(即 ascii、latin-1、utf-8、utf-16 等)相同吗?

标签: java inputstream


【解决方案1】:

将缓冲输入和输出流与 try-with-resources 一起使用
(确保流在 EOJ 时全部关闭)
像这样的:

try(final InputStream  ist = new URL(url).openStream ();
    final InputStream  bis = new BufferedInputStream (ist);

    final OutputStream ost = new     FileOutputStream(file);
    final OutputStream bos = new BufferedOutputStream(ost))
{
    final byte[] bytes = new byte[64_000]; // <- as large as possible!
    /**/  int    count;

    while ((count = bis.read(bytes)) != -1) {
        bos.write(bytes, 0, count);
    }
}

【讨论】:

  • 感谢您的回答,我没想到要读取十个字节或十个字节或更多:)
  • InputStream.transferTo(OutputStream) 没问题并使用 8192 Bufsize。如果您想使用更大的缓冲区,那么您仍然必须使用老式的方式。可惜他们没有在 transferTo(...) 方法中添加长度参数。
  • @DaveTheDane 您可以使用BufferedInputStream(InputStream, int)BufferedOutputStream(OutputStream, int) 构造函数来调整缓冲区大小。我不确定添加第三个(尽可能大的)缓冲区有多大价值。
  • @ElliottFrisch 关于缓冲区大小:我指的是InputStream.transferTo(...)org.apache.commons.io.IOUtils.copyLarge(InputStream, OutputStream, byte[]) 做了类似的事情。通过提供 byte[],您可以完全掌控。
猜你喜欢
  • 2022-07-12
  • 2010-10-12
  • 2019-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多