java - 下载文件而不知道其大小

标签 java file memory download

我正在使用 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/

相关文章:

mysql - 缓存与数据库查询

python - Python 中的数据局部性优化

memory - CUDA 结果可以存储在 OpenGL 可访问的纹理中吗?

memory - 为什么哈希表比其他数据结构占用更多内存?

java - Spring Boot 3.0.0 + Spring Cloud 2021.0.5 未定义负载平衡的 Feign 客户端。您是否忘记包含 spring-cloud-starter-loadbalancer ?

java - Hibernate:使用 setFirstResult 和 setMaxResult 进行分页

java - 使用 JGit TreeWalk 列出文件和文件夹

java - 在 JUnit 中删除文件和目录

java - Java 上的文件中的某些字符读取为问号 (?)

java - 从 jdbc 连接到 oracle 服务器获取 Activity 主机和端口(不要解析 url)