下载文件时不知道其大小



我正在使用URLConnection, DataInputStream和FileOutputStream下载文件。我正在创建一个巨大的字节[]与在线文件的大小(与getContentLength())。问题是,当我尝试下载大文件时,我得到一个OutOfMemoryError: Java堆空间,这是一个正常的行为。

代码如下:

    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();    

我听说我应该把文件分割成块来避免它。我知道怎么做,很简单,但是…我怎么能做到这一点,如果文件的ContentLength不能从服务器(getContentLength() == -1)红色?如果我不知道文件的大小,我该如何将文件分割成块呢?

谢谢!

我正在创建一个巨大的字节[]与在线文件的大小

为什么?您不需要文件大小的字节数组。这只会浪费空间并增加延迟。只读和写入缓冲区:

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

对于任何大于0的byte[]缓冲区都有效。我一般用8192

使用URLConnection,您也不需要内容长度:只需像上面那样读取到EOS。

根本没有理由使用DataInputStream。使用Files:

final Path dstFile = Paths.get("path/to/dstfile");
Files.copy(url.openStream(), dstFile);

相关内容

  • 没有找到相关文章

最新更新