下载文件或zip文件的Java代码

下载文件或zip文件的Java代码,java,Java,我正在使用下面的代码下载一个文件,它可以很好地用于小文件,但当我尝试下载一个大小>11GB的文件时,代码不起作用,并给出java.lang.NegativeArraySizeException异常 public String downloadDirectory() { OutputStream myOut = null; FileInputStream fileInputStream = null; File downzip = new File(dirName+

我正在使用下面的代码下载一个文件,它可以很好地用于小文件,但当我尝试下载一个大小>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
异常

您正在读取长格式的数据大小,并将其向下转换为int格式,这是不安全的,并且会导致数组长度为负数。实际上,如果我按照这段代码的话,你的文件长度应该是0,长度可能不是负数,而只是零

作为解决方案,请尝试直接写入文件,而不是预先创建数组。另外,为阵列分配11G内存也不是一个好主意


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

您正在长时间读取数据大小并将其向下转换为int,这是不安全的,并导致数组长度为负。实际上,如果我按照这段代码的话,你的文件长度应该是0,长度可能不是负数,而只是零

作为解决方案,请尝试直接写入文件,而不是预先创建数组。另外,为阵列分配11G内存也不是一个好主意


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

Intger.MAX\u值为
2^31-1
。在常规数组中只能存储
2^31-1
字节
2GiB

Java使用int进行数组索引。
Intger.MAX\u值为
2^31-1
。您只能在常规数组中存储
2^31-1
字节
2GiB

您将其存储到字节数组中,对于字节数组,11GB的存储空间相当大,我认为出现了问题


请提供获得错误的确切行。

您将其存储到字节数组中,11 GB的字节数组存储起来相当大,我认为出现了问题


请提供获得错误的确切行。

导致您出现问题的是
文件downzip的长度

downzip.length()
返回
long
,您可以将其显式转换为
int
。通过这种方式,您可以轻松获得初始化数组时使用的负值:

byte[] dataRead = new byte[(int)downzip.length()];
另一件事是你应该避免阅读整个文件。更好的方法是分块读写


在@Ashok Raj的回答中有一个例子说明了如何做到这一点。

文件downzip的长度给您带来了问题

downzip.length()
返回
long
,您可以将其显式转换为
int
。通过这种方式,您可以轻松获得初始化数组时使用的负值:

byte[] dataRead = new byte[(int)downzip.length()];
另一件事是你应该避免阅读整个文件。更好的方法是分块读写


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

您不是在循环中尝试过吗?像这样

 byte data[] = new byte[1024];
 int count;
  while ((count = in.read(data, 0, 1024)) != -1)
            {
                    out.write(data, 0, count);
            }

你没试过打圈吗?像这样

 byte data[] = new byte[1024];
 int count;
  while ((count = in.read(data, 0, 1024)) != -1)
            {
                    out.write(data, 0, count);
            }
使用此方法:

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的文件上使用此方法:

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的文件上成功地使用了它

错误来自哪一行?11GB太大,无法放入
int
中。你的问题是什么?我也希望你有办法恢复下载。要通过11GB获得90%的数据,并且必须重新开始,这将是相当痛苦的。你的意思是这行新字节[(int)downzip.length()]?适合int的最大值约为2GB。如果您的文件是11 GB,它将溢出并可能导致负值。错误来自哪一行?11GB太大,无法放入
int
中。你的问题是什么?我也希望你有办法恢复下载。要通过11GB获得90%的数据,并且必须重新开始,这将是相当痛苦的。你的意思是这行新字节[(int)downzip.length()]?适合int的最大值约为2GB。如果您的文件为11 GB,它将溢出并可能导致负值。我应该在代码中做哪些修改以允许下载大文件?如果您希望处理整个字节,并将数组拆分为较小的部分,则应使用64位java实现。如果只保存它们,只需将其读取到缓冲区并写入。我应该在代码中做哪些修改以允许下载大文件?如果要处理整个字节,并将数组拆分为更小的部分,则应使用64位java实现。如果您只是保存这些文件,只需将其读取到缓冲区并写入。我应该在代码中做哪些修改以允许下载大文件?@ankit如果您一次下载整个文件,则永远不应该这样做,即使是小文件。使用一个内部缓冲区并循环以较小的块下载文件。我应该在代码中做哪些修改以启用大文件下载?@ankit如果您一次下载整个文件,则不应该这样做,即使是小文件。使用内部缓冲区并使用循环迭代以较小的块下载文件错误在此行:byte[]dataRead=new byte[(int)downzip.length();对于大文件,值(int)downzip.length()变为负值,并给出java.lang.NegativeArraySizeException异常。如果要将downzip.length()转换为int,可以使用for循环存储它,在一次迭代中只存储字节(而不是int)的大小然后将其写入文件并继续循环,直到所有数据都被复制。错误出现在这一行:byte[]dataRead=new byte[(int)downzip.length();值(int)downzip.len