Reputation: 13
In my android app, I am reading a file from internal storage every time a new game loads. The first 4 times I do this, it works fine, but on the fifth time it force closes. Here is my code
private String readFromInternalStorage(String filename) {
FileInputStream fis=null;
byte[] bytes = new byte[1000000];
try {
fis=startGame.openFileInput(filename);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fis.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
return new String(bytes);
}
While messing around with the code, I noticed that if I change the length of the byte array, it changes the amount of times I can read a file without it force closing. If I change the length to 2000000, it closes after the second time and if I change it to 100000 it closes after the eighth time. I'm pretty clueless as to why this would happen because I am creating a new byte array every time the method is called so I wouldn't think that the size would change anything.
Update:
After going back and doing some more testing it seems like file input has nothing to do with why my app is force closing. When this code is commented out, the app will load five levels in a row without force closing so I thought that it was the problem, but it still force closes after eight tries so clearly there's something else that's not working. Thanks for your help anyway.
Upvotes: 0
Views: 362
Reputation: 63955
a safe version of what you do is e.g.:
private String readFromInternalStorage(String filename) {
FileInputStream fis = null;
File file = new File(startGame.getFilesDir(), filename);
long size = file.length();
// impossible to have more than that (= 2GB)
if (size > Integer.MAX_VALUE) {
Log.d("XXX", "File too big");
return null;
}
int iSize = (int) size;
try {
fis = new FileInputStream(file);
// part of Android since API level 1 - buffer can scale
ByteArrayBuffer bb = new ByteArrayBuffer(iSize);
// some rather small fixed buffer for actual reading
byte[] buffer = new byte[1024];
int read;
while ((read = fis.read(buffer)) != -1) {
// just append data as long as we can read more
bb.append(buffer, 0, read);
}
// return a new string based on the large buffer
return new String(bb.buffer(), 0, bb.length());
} catch (FileNotFoundException e) {
Log.w("XXX", e);
} catch (IOException e) {
Log.w("XXX", e);
} catch (OutOfMemoryError e) {
// this could be left out. Keep if you read several MB large files.
Log.w("XXX", e);
} finally {
// finally is executed even if you return in above code
// fis will be null if new FileInputStream(file) throws
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// ignored, nothing can be done if closing fails
}
}
}
return null;
}
Upvotes: 0
Reputation: 2724
You shouldn't hard-code the array size. Besides you should use finally, in order to make sure the FileInputStream
is closed, even when failed.
Here's a code sample that shows how it should be done:
FileInputStream fis;
String info = "";
try {
fis = mContext.openFileInput(this.fileName);
byte[] dataArray = new byte[fis.available()];
if (dataArray.length > 0) {
while (fis.read(dataArray) != -1) {
info = new String(dataArray);
}
Log.i("File Reading" , "Success!");
isOk = true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
fis.close();
}
Upvotes: 1