I am using below code to download a file and it works fine for small files, but when I tried to download a file whose size > 11GB code is not working and giving java.lang.NegativeArraySizeException
exception
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();;
}
}
}
}
The error is at this line:
byte[] dataRead = new byte[(int)downzip.length()];
The value (int)downzip.length()
becomes negative for big files and gives java.lang.NegativeArraySizeException
exception.
didn't you try in a loop? like this
byte data[] = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1)
{
out.write(data, 0, count);
}
You are reading data size in long and down casting it into int, which is not safe, and is causing the negative array length. Actually your file length should be 0 if I go by this code, and the length may not be negative but simply zero.
As a solution, try writing directly to a file instead of creating an array upfront. Also, allocating 11G memory for array is anyway not a good idea.
You can create a FileOutputStream
from the output file path and then read from the InputStream
and write to OutputStream
until you reach the end of stream -1
that should safely copy file for you.
You are storing it into byte array for which 11 GB is quite big to store that, i think there is the problem occur.
Please provide the exact line where you got the error.
Java use int for array indexing. The Intger.MAX_VALUE
is 2^31-1
. You can store only 2^31-1
bytes 2GiB
in a regular array.
It is the length of File downzip
that causing you a problem.
downzip.length()
returns long
, which you explicitly cast to int
. That way you easily get negative value with which you initialize array:
byte[] dataRead = new byte[(int)downzip.length()];
Another thing is you should avoid reading a whole file. Better way would be reading and writing it in chunks.
You have example of how to do this in @Ashok Raj's answer.
Use this method:
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();
}
}
I have successfully used it, on up to 20GB files
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.