MSmall
MSmall

Reputation: 13

Android force closes when reading from internal storage 5 times in a row

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

Answers (3)

zapl
zapl

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

RE6
RE6

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

paulsm4
paulsm4

Reputation: 121799

I don't see a "close()" in your code:

Upvotes: 3

Related Questions