将二进制数据从URL复制到Java中的文件,无需中间副本

Luk*_*ell 4 java url copy file

我正在更新一些旧代码以从URL而不是从数据库中获取一些二进制数据(数据将被移出数据库,并且可以通过HTTP访问).数据库API似乎直接将数据提供为原始字节数组,并且有问题的代码使用BufferedOutputStream将此数组写入文件.

我对Java一点都不熟悉,但是谷歌上的一些谷歌搜索让我看到了这段代码:

URL u = new URL("my-url-string");
URLConnection uc = u.openConnection();
uc.connect();
InputStream in = uc.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
final int BUF_SIZE = 1 << 8;
byte[] buffer = new byte[BUF_SIZE];
int bytesRead = -1;
while((bytesRead = in.read(buffer)) > -1) {
    out.write(buffer, 0, bytesRead);
}
in.close();
fileBytes = out.toByteArray();
Run Code Online (Sandbox Code Playgroud)

这似乎在大多数情况下都有效,但是当复制的数据很大时我遇到了问题 - 对于使用旧代码工作正常的数据项,我得到一个OutOfMemoryError.

我猜这是因为这个版本的代码同时在内存中有多个数据副本,而原始代码没有.

有没有一种简单的方法可以从URL中获取二进制数据并将其保存在文件中,而不会在内存中产生多个副本的成本?

Aym*_*ieh 12

您可以通过替换以下内容将其直接写入文件,而不是将数据写入字节数组然后将其转储到文件中:

ByteArrayOutputStream out = new ByteArrayOutputStream();
Run Code Online (Sandbox Code Playgroud)

附:

FileOutputStream out = new FileOutputStream("filename");
Run Code Online (Sandbox Code Playgroud)

如果您这样做,则最后无需拨打电话out.toByteArray().只需确保FileOutputStream在完成后关闭对象,如下所示:

out.close();
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅FileOutputStream的文档.

  • 您可能想尝试使用URLConnection.getContentLength()来查找数据长度而不是缓冲. (2认同)