Android application crashes while defining byte buffer to read a file - java

I am trying to read a file into a byte buffer in android. The application crashes whenever I initialize the byte buffer with the size equal to the size of the file. I have checked correctly and the file size is well below the int max value. Because of certain project setup, I have to test the application on the device due to which I don't have the access to the logcat.
File outputdir = new File(localcontext.getFilesDir(), "appData");
if(!outputdir.exists()){
if(outputdir.mkdir()){
Toast.makeText(localcontext, outputdir.getAbsolutePath(), Toast.LENGTH_SHORT).show();
}
}
tempfile = new File(outputdir, "runningfile.mp4");
bytebuffer = new byte[(int)encryptedfile.length()];
OutputStream os = new FileOutputStream(tempfile.getAbsolutePath(), false);
// DataInputStream dataInputStream = new DataInputStream(fis);
// dataInputStream.readFully(bytebuffer);
// dataInputStream.close();
The application runs fine and displays some message when I comment out the byte buffer initialization line but crashes otherwise.
I am unable to figure out what's wrong here. Please help. Thanks.

Use try catch block and display error with toast.
try{
bytebuffer = new byte[(int)encryptedfile.length()];
}catch(Exception e){
Toast.makeText(getActivity(), e.getMessage(),Toast.LENGTH_LONG).show();
}

Related

Clear contents of file without deletion

I'm developing a sound recognition app on android and am using the MediaRecorder class as well as a tensorflow model. I create the audio file where I will be saving the recorder microphone audio in the onCreate method for the class
audioFile = getExternalCacheDir().getAbsolutePath();
audioFile += "/Recording.3gp";
And I set the output file of the mediaRecorder to this file in the startRecording class
mediaRecorder.setOutputFile(audioFile);
The issue im having is that I need to convert the recording into a series of MFCC values for the model to work, and the MFFC.java class im using requires that the recording be converted to a double array. I'm doing that like this
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(audioFile));
int read;
byte[] buff = new byte[1024];
while ((read = in.read(buff)) > 0)
{
out.write(buff, 0, read);
}
out.flush();
byte[] bytes = out.toByteArray();
int times = Double.SIZE / Byte.SIZE;
double[] doubleArray = new double[bytes.length / times];
for(int i=0;i<doubleArray.length;i++){
doubleArray[i] = ByteBuffer.wrap(bytes, i*times, times).getDouble();
}
Which is how they said to do it on another stack overflow post. The issue with this is that the audio file im sending the recording(s) to just keeps adding the new recordings to previous ones. This is because I am recording the audio then passing it to my classifier method in a loop like so
while(true){
try {
soundRecognition task = new soundRecognition();
task.execute();
sleep(1500);
}
Solutions I have tried
I have tried to move the creation of the audio to the sound recognition class but I cant do that as it produces errors, specifically mediaRecorder start called in invalid state: 4.
I have tried to overwrite the file using a FileWriter and PrintWriter class, but this didnt work, im assuming because the file is and audio file.
Any help would be appreciated

File from InputStream

Yes, this question has been asked a millions times, and I believe I've looked at them all. They are very "sometimesy", slow, or not what I need.
On one project, I use the following code to use the InputStream received from a GET to turn that into a PDF. This works PERFECTLY, every time, on my physical device and my emulator (Genymotion 2.1.1, Emulator API 18 4.3). Note that some things are edited out, and the PDFs are generally small, less than 1 MB.
public abstract class MyPDFFile extends File implements ApiModel{
public MyPDFFile(InputStream inputStream){
super(context.getExternalFilesDir(
Environment.DIRECTORY_DOWNLOADS), "my_pdf.pdf");
if (externalStorageIsWritable()) {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
FileOutputStream fileInputStream = new FileOutputStream(this);
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileInputStream));
int readLine;
char[] cbuf = new char[1];
do {
readLine = bufferedReader.read(cbuf);
bufferedWriter.write(cbuf);
} while (readLine != -1);
bufferedWriter.close();
}
catch(IOException e){
// Didn't work
}
}
else{
// Cant write
}
}
I figured on this new project, I could use the same code to download an APK from the internet to the device. Nope, definitely not the case. I eventually tried this for Inputstream to File:
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] buffer = new byte[1];
while ( (read(buffer)) > 0 ) {
fileOutputStream.write(buffer);
}
fileOutputStream.close();
close();
That works on my emulator, and works fine. I moved to testing on my device... not so much, which is weird, because the working PDF code works on both my emulator and device. I've tried adjusting the size of my buffer to various multiples of 512 (which results in the file being EXTREMELY small, like a few KB, to being EXTREMELY large, about double the apk size, which is about 5.6 MB).
Also, another weird thing: I can NEVER get it to successfully save outside of the constructor. When I do the saving there, the InputStream is fine, my file gets created, yadayada, and when I use successful code, I just rename the file afterwards since all I have access to in the constructor is the InputStream. If I decide "No, I want to name it when I have the proper things" and simply save the InputStream to my object, it NEVER works properly. Can never get above 4KB for the downloaded file. I've tried extends InputStream and extends BufferedInputStream to no avail.
I can post more code if needed. All I would have access to is the InputStream from my GET request; I'm using the browep Android HTTP library and that's all I can get without trying to mess with the library itself (or overriding methods in it).
The problem is that you're reading the file byte by byte. This can take ton of time. Instead, read the file in bigger piece of chunks, like 4 or 8 KBs:
int file_chunk_size = 1024 * 4; //4KBs, written like this to easily change it to 8
byte[] buffer = new byte[file_chunk_size];
int bytesRead = 0;
while ( (bytesRead = read(buffer)) > 0 ) {
fileOutputStream.write(buffer, 0, bytesRead);
}

Zlib compression is too big in size

I am completely new to java, I have decided to learn it by doing a small project in it. I need to compress some string using zlib and write it to a file. However, file turn out to be too big in size. Here is code example:
String input = "yasar\0yasar"; // test input. Input will have null character in it.
byte[] compressed = new byte[100]; // hold compressed content
Deflater compresser = new Deflater();
compresser.setInput(input.getBytes());
compresser.finish();
compresser.deflate(compressed);
File test_file = new File(System.getProperty("user.dir"), "test_file");
try {
if (!test_file.exists()) {
test_file.createNewFile();
}
try (FileOutputStream fos = new FileOutputStream(test_file)) {
fos.write(compressed);
}
} catch (IOException e) {
e.printStackTrace();
}
This write a 1 kilobytes file, while the file should be at most 11 bytes (because the content is 11 bytes here.). I think problem is in the way I initialize the byte array compressed as 100 bytes, but I don't know how big the compreesed data will be in advance. What am I doing wrong here? How can I fix it?
If you don't want to write the whole array and instead write just the part of it that was filled by Deflater use OutputStream#write(byte[] array, int offset, int lenght)
Roughly like
String input = "yasar\0yasar"; // test input. Input will have null character in it.
byte[] compressed = new byte[100]; // hold compressed content
Deflater compresser = new Deflater();
compresser.setInput(input.getBytes());
compresser.finish();
int length = compresser.deflate(compressed);
File test_file = new File(System.getProperty("user.dir"), "test_file");
try {
if (!test_file.exists()) {
test_file.createNewFile();
}
try (FileOutputStream fos = new FileOutputStream(test_file)) {
fos.write(compressed, 0, length); // starting at 0th byte - lenght(-1)
}
} catch (IOException e) {
e.printStackTrace();
}
You will probably still see 1kB or so in Windows because what you see there seems to be either rounded (you wrote 100 bytes before) or it refers to the size on the filesystem which is at least 1 block large (should be 4kb IIRC). Rightclick the file and check the size in the properties, that should show the actual size.
If you don't know the size in advance, don't use Deflater, use a DeflaterOutputStream that writes data of any length compressed.
try (OutputStream out = new DeflaterOutputStream(new FileOutputStream(test_file))) {
out.write("hello!".getBytes());
}
Above example will use the default values for deflating but you can pass a configured Deflater in the constructor of DeflaterOutputStream to change the behavior.
you write to file all 100 bytes of compressed array, but you have to write only really compressed bytes returned by deflater.
int compressedsize = compresser.deflate(compressed);
fos.write(compressed, 0, compressedsize);

android tcp client file receive

I am trying to send a file (png to be specific) over sockets from python server to android client. I know that my python server is sending the data, I just can't figure out how to receive the data on the android side. Here is what the code looks like to receive the file.
String path = Environment.getExternalStorageDirectory().toString() +"/tmp/test.png";
try {
socket = new Socket("192.168.1.129", 29877);
is = socket.getInputStream();
out = new FileOutputStream(path);
byte[] temp = new byte[1024];
for(int c = is.read(temp,0,1024); c > 0; c = is.read(temp,0,1024)){
out.write(temp,0,c);
Log.d("debug tag", out.toString());
}
Log.d("debug tag", temp.toString());
Bitmap myBitmap = BitmapFactory.decodeByteArray(temp, 0, temp.length);
imageView.setImageBitmap(myBitmap);
Thanks for any advice.
You are reading from socket in 1K chunks and saving them into a file. Then you try to interpret the last chunk as a bitmap. This doesn't work.
Either read your image from the file after you saved it, or buffer it all in memory.

java program download file is corrupt. Why?

I have created a java program that downloads a file from a URL part by part into several files, then reads the bytes from those files into the full downloaded object. It works by separating sections of the file to be downloaded into threads. Every time my program downloads a file it gets all of the bytes and the file size is correct, but sometimes with an image the picture is distorted. Other times the image is perfect. What would cause this?
code that individual threads use to download file parts:
URL xyz = new URL(urlStr);
URLConnection connection= xyz.openConnection();
// set the download range
connection.setRequestProperty("Range", "bytes="+fileOffset+"-");
connection.setDoInput(true);
connection.setDoOutput(true);
// set input stream and output stream
in = new BufferedInputStream(connection.getInputStream());
fos = new FileOutputStream("part_"+this.partNumber);
out = new BufferedOutputStream(fos, this.downloadFileSize);
// create buffer to read bytes from file into
byte[] contentBytes = new byte[downloadFileSize];
// read contents into buffer
in.read(contentBytes, 0, this.downloadFileSize);
out.write(contentBytes, 0, this.downloadFileSize);
code that puts file together:
int partSize=0;
//Create output stream
OutputStream saveAs = new FileOutputStream(fileName);
for(int i=0; i<filePieces;i++)
{
File file=new File("part_"+(i+1));
partSize=(int)file.length();
byte fileBuffer[]=new byte [partSize];
//Create input stream
InputStream is = new FileInputStream(file);
is.read(fileBuffer);
saveAs.write(fileBuffer);
is.close();
}
Without further details and sample code you're forcing any answers to be guesses. Here are mine:
You're using Readers and Writers when you should use Input- / OutputStreams.
You've messed up the synchronization somehow. Favour classes from the java.util.concurrent package over home grown synchronized solutions.

Categories