我正在使用 URLConnection、DataInputStream 和 FileOutputStream 下载文件。我正在创建一个巨大的 byte[] ,其大小与在线文件的大小(使用 getContentLength() )。问题是,当我尝试下载大文件时,出现 OutOfMemoryError: Java heap space,这是正常行为。
这是代码:
URLConnection con;
DataInputStream dis;
FileOutputStream fos;
byte[] fileData = null;
URL url = new URL(from);
con = url.openConnection();
con.setUseCaches(false);
con.setDefaultUseCaches(false);
con.setRequestProperty("Cache-Control", "no-store,max-age=0,no-cache");
con.setRequestProperty("Expires", "0");
con.setRequestProperty("Pragma", "no-cache");
con.setConnectTimeout(5000);
con.setReadTimeout(30000);
dis = new DataInputStream(con.getInputStream());
int contentLength = con.getContentLength();
//Taille connue
if (contentLength != -1)
{
fileData = new byte[con.getContentLength()];
for (int x = 0; x < fileData.length; x++)
{
fileData[x] = dis.readByte();
if (listener != null)
{
listener.onFileProgressChanged(x, fileData.length);
}
}
}
//Taille inconnue
else
{
System.out.println("Attention : taille du fichier inconnue !");
if (undefinedListener != null)
{
undefinedListener.onUndefinedFile();
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
while (true)
{
try
{
stream.write(dis.readByte());
}
catch (EOFException ex)
{
//Fin
fileData = stream.toByteArray();
stream.close();
}
}
}
dis.close();
//Ecriture
fos = new FileOutputStream(file);
fos.write(fileData);
fos.close();
我听说我应该将文件分成 block 以避免它。我知道如何做到这一点,这很简单,但是...如果文件的 ContentLength 不能从服务器变为红色 (getContentLength() == -1) ,我该怎么做?如果我不知道文件的大小,我应该如何将文件分成 block ?
谢谢!
最佳答案
为什么?您不需要文件大小的字节数组。这只会浪费空间并增加延迟。只需读取和写入缓冲区:I am creating a huge byte[] with the size of the online file
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
这适用于任何大小大于零的 byte[] 缓冲区。我一般用8192。
使用 URLConnection,您也不需要内容长度:只需如上所述读取 EOS。
关于java - 下载文件而不知道其大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22489553/