0

我正在使用以下代码下载文件,它适用于小文件,但是当我尝试下载大小> 11GB 的文件时,代码不起作用并出现java.lang.NegativeArraySizeException异常

public String downloadDirectory()
{

     OutputStream myOut = null;
     FileInputStream fileInputStream = null;
     File downzip = new File(dirName+"/"+dir+".zip");


   getServletResponse().setContentType("TEXT/HTML");
   getServletResponse().setHeader("Content-Disposition","attachment; filename=\"" + dir +".zip" + "\"");
   getServletResponse().setContentLength((int)downzip.length());
    System.out.println("length  "+(int)downzip.length());
     //READ DATA FROM FILE

            byte[] dataRead = new byte[(int)downzip.length()];
               fileInputStream = new FileInputStream(downzip);
               fileInputStream.read(dataRead,0,(int)downzip.length());
    //WRITE DATA TO OUTFILE
               myOut = getServletResponse().getOutputStream();


          myOut.write(dataRead);

           if (fileInputStream != null) {                       
               fileInputStream.close();
           }



    }
    catch(Exception e)
    {
        e.printStackTrace();
         Execute.rmdirscript(dirName);
        return "exception";
    }
     finally{
        System.out.println("finally downloaddir");
    if(myOut!=null){
        try{
        myOut.close();}
        catch(Exception e){
            e.printStackTrace();;
        }
    }
    if (fileInputStream != null) {                       
               try{
        fileInputStream.close();}
        catch(Exception e){
            e.printStackTrace();;
        }
           }
}


}

错误在这一行:

byte[] dataRead = new byte[(int)downzip.length()];

对于大文件,该值(int)downzip.length()变为负数并给出java.lang.NegativeArraySizeException异常。

4

6 回答 6

3

你没有尝试循环吗?像这样

 byte data[] = new byte[1024];
 int count;
  while ((count = in.read(data, 0, 1024)) != -1)
            {
                    out.write(data, 0, count);
            }
于 2012-10-04T09:18:01.743 回答
2

您正在读取 long 和 down 的数据大小,将其转换为 int,这是不安全的,并且会导致负数组长度。实际上,如果我使用此代码,您的文件长度应该为 0,并且长度可能不是负数,而只是零。

作为一种解决方案,尝试直接写入文件而不是预先创建数组。此外,为数组分配 11G 内存无论如何也不是一个好主意。

您可以从输出文件路径创建一个FileOutputStream,然后读取InputStream并写入,OutputStream直到您到达-1应该为您安全地复制文件的流的末尾。

于 2012-10-04T09:10:42.533 回答
1

您将它存储到 11 GB 相当大的字节数组中,我认为有问题发生。

请提供您收到错误的确切行。

于 2012-10-04T09:14:52.017 回答
0

使用此方法:

private static void readFileAndDumpIt(String pathToFile, OutputStream out){
    try {
        InputStream fIs = new BufferedInputStream(new FileInputStream(pathToFile));
        byte[] array=new byte[4096];
        for(int numberRead=fIs.read(array);numberRead!=-1;numberRead=fIs.read(array)){
            out.write(array,0,numberRead);
            out.flush();
        }
        fIs.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我已经成功使用它,最多 20GB 的文件

于 2012-10-04T11:03:46.940 回答
0

Java 使用 int 进行数组索引。Intger.MAX_VALUE2^31-1。_ 您只能将2^31-1字节存储2GiB在常规数组中。

于 2012-10-04T09:12:19.180 回答
0

File downzip这是导致您出现问题的长度。

downzip.length()返回long,您明确地转换为int. 这样,您可以轻松获得初始化数组的负值:

byte[] dataRead = new byte[(int)downzip.length()];

另一件事是您应该避免读取整个文件。更好的方法是分块读取和写入。

您在@Ashok Raj 的回答中有如何做到这一点的示例。

于 2012-10-04T09:16:55.307 回答