I have tried for 200 MB of image file and converting it onto byte array but is crashed due to OOM, so how to read large file and converting into byte[]
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 210288697 byte allocation with 4108138 free bytes and 186MB until OOM
byte[] fullyReadFileToBytes(File file) throws IOException {
int size = (int) file.length();
byte bytes[] = new byte[size];
byte tmpBuff[] = new byte[size];
FileInputStream fis = new FileInputStream(file);
try {
int read = fis.read(bytes, 0, size);
if (read < size) {
int remain = size - read;
while (remain > 0) {
read = fis.read(tmpBuff, 0, remain);
System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
remain -= read;
}
}
} catch (IOException e) {
throw e;
} finally {
fis.close();
}
return bytes;
}
NOTE: I have tried for 100MB and it is working perfect but in case of size greater than 150MB it's creating crash.
Use Http post multipart transfer i.e.
ByteArrayInputStream fileInputStream = new ByteArrayInputStream(dataFile.getContent());
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024 * 1024;//1 mb buffer - set size according to your need
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dataOutputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dataOutputStream.writeBytes(lineEnd);
Use volley multi-transfer request. It will keep track of failures
https://gist.github.com/anggadarkprince/a7c536da091f4b26bb4abf2f92926594
The below code helps to compress the bitmap image and convert to string bytes.
public String BitMapToString(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
byte[] b = baos.toByteArray();
String temp = null;
try {
System.gc();
temp = Base64.encodeToString(b, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
b = baos.toByteArray();
temp = Base64.encodeToString(b, Base64.DEFAULT);
}
return temp;
}
Related
I try upload image to server. I get image by path and convert it to byte array:
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap picture = BitmapFactory.decodeFile(imagePath, bmOptions);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bao);
byte[] bytes = bao.toByteArray();
builder.addPart("uploadedfile", new ByteArrayBody(bytes, "name" + ".jpg"));
For example image's size is 300kb but size of uploaded image is 800kb.
How can I send image (selected by path) without size increasing?
SOULUTION
#greenapps right. I converted image as file:
public static byte[] fullyReadFileToBytes(File f) throws IOException {
int size = (int) f.length();
byte bytes[] = new byte[size];
byte tmpBuff[] = new byte[size];
FileInputStream fis= new FileInputStream(f);;
try {
int read = fis.read(bytes, 0, size);
if (read < size) {
int remain = size - read;
while (remain > 0) {
read = fis.read(tmpBuff, 0, remain);
System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
remain -= read;
}
}
} catch (IOException e){
throw e;
} finally {
fis.close();
}
return bytes;
}
Put the image file in a byte array without using an intermediate Bitmap.
I am trying to convert a file from the sdcard to Base64 but it seems the file is too big and i get an OutOfMemoryError.
Here is my code :
InputStream inputStream = null;//You can get an inputStream using any IO API
inputStream = new FileInputStream(file.getAbsolutePath());
byte[] bytes;
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
bytes = output.toByteArray();
attachedFile = Base64.encodeToString(bytes, Base64.DEFAULT);
Is there a way to go around the OutOfMemoryError while filing the String attachedFile ?
Base64 encoding takes 3 input bytes and converts them to 4 bytes. So if you have 100 Mb file that will end up to be 133 Mb in Base64. When you convert it to Java string (UTF-16) it size will be doubled. Not to mention that during conversion process at some point you will hold multiple copies in memory. No matter how you turn this it is hardly going to work.
This is slightly more optimized code that uses Base64OutputStream and will need less memory than your code, but I would not hold my breath. My advice would be to improve that code further by skipping conversion to string, and using temporary file stream as output instead of ByteArrayOutputStream.
InputStream inputStream = null;//You can get an inputStream using any IO API
inputStream = new FileInputStream(file.getAbsolutePath());
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
output64.close();
attachedFile = output.toString();
// Converting File to Base64.encode String type using Method
public String getStringFile(File f) {
InputStream inputStream = null;
String encodedFile = "", lastVal;
try {
inputStream = new FileInputStream(f.getAbsolutePath());
byte[] buffer = new byte[10240]; //specify the size to allow
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
output64.close();
encodedFile = output.toString();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
lastVal = encodedFile;
return lastVal;
}
I want to record a mp4 file from bitmap arraylist.My code:
File directory = intiFilePath();
DataOutputStream out = new DataOutputStream(new FileOutputStream(directory.getPath()+"/test.mp4"));
int maxBufferSize = 256 * 1024;// 256KB
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
for (Bitmap n : bmpList) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
n.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] bitmapdata = bos.toByteArray();
ByteArrayInputStream bs = new ByteArrayInputStream(bitmapdata);
DataInputStream in = new DataInputStream(bs);
bytesAvailable = in.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = in.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
out.write(buffer, 0, bytesRead);
out.flush();
bytesAvailable = in.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = in.read(buffer, 0, bufferSize);
}
in.close();
}
out.close();
But the mp4 file cannot play (the file is exist).
Anyone can help me what's wrong.
Sorry, but you can't. Try use OpenCv lib
I have an API call that returns a byte array. I currently stream the result into a byte array then make sure the checksums match and then write the ByteArrayOutputStream to File. The code is something like this and it works pretty well.
String path = "file.txt";
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
FileOutputStream stream = new FileOutputStream(path);
stream.write(byteBuffer.toByteArray());
My concern i that the result from inputstream could potentially be larger than the heap size in android and I could get OutOfMemory exceptions if the entire byte array is in memory. What is the most elegant way to write the inputStream to file in chunks, such that the byte array is never larger than the heap size?
Don't write to the ByteArrayOutputStream. Write directly to the FileOutputStream.
String path = "file.txt";
FileOutputStream output = new FileOutputStream(path);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, len);
}
I went with the advice to skip the ByteArrayOutputStream and write to the FileOutputStream and this seems to address my concerns. With one quick adjustment, where the FileOutputStream is decorated by a BufferedOutputStream
String path = "file.txt";
OutputStream stream = new BufferedOutputStream(new FileOutputStream(path));
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = is.read(buffer)) != -1) {
stream.write(buffer, 0, len);
}
if(stream!=null)
stream.close();
In the following code:
fileInputStream = new FileInputStream(new File(pathToOurFile) );
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
Printing buffer is giving some random value, instead of what is there in file. buffersize is properly calculating the size of the file.
Can you tell wat is going wrong?
Try this..
private void ReadFile(AssetManager manager, String sourceFileName,
String destinationFileName) throws IOException {
// Read file from AccessManager
InputStream inputStream = manager.open(sourceFileName);
OutputStream outputStream = new FileOutputStream(destinationFileName);
Log.d("-->", "src: " + sourceFileName);
Log.d("-->", "Des: " + destinationFileName);
byte[] buffer = new byte[3072];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
outputStream = null;
inputStream = null;
}