I've just released an Android app that parses a local file and make some process with the data. Some days ago one of my customers has reported me an error, each time he tries to process his file the app crashes.
This is the error log he sent me:
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.NullPointerException: lock == null
at java.io.Reader.<init>(Reader.java:64)
at java.io.InputStreamReader.<init>(InputStreamReader.java:120)
And the code related to this is this:
// EDIT 1: Following greenapps comment I will put a more realistic version of this
// method (The first version was invented because I wanted to be breaf)
public void selectFile()
{
List<File> files = getDocsToParse();
this.listview.setAdapter(this.myadapter);
this.listview.setOnItemClickListener(new OnItemClickListener()
{
...
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
parseFile(files.get(position));
}
...
}
this.myadapter.addFiles(files);
}
public static List<File> getDocsToParse() {
File sdcard = Environment.getExternalStorageDirectory();
File subdir = new File(sdcard, "MyAppFolder/Files/");
// EDIT 2: I'm using subdir.mkdirs(); because I want to
// create MyAppFolder/Files/ folders the first time the user use the app.
// Is this not correct? Should I create these folders any other way?
if (!subdir.exists()) {
subdir.mkdirs();
}
File files[] = subdir.listFiles();
List<File> filterFiles = new ArrayList<File>();
for (int i = 0; i < files.length; i++) {
File file = files[i];
filterFiles.add(file);
}
return filterFiles;
}
public void parseFile(File fileToParse)
{
long totalSize = 0;
InputStream is = null;
try {
totalSize = fileToParse.length();
is = new BufferedInputStream(new FileInputStream(fileToParse));
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader reader = null;
reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String line = "";
StringTokenizer st = null;
try {
while ((line = reader.readLine()) != null) {
// Here I parse the file
}
} catch (IOException e) {
e.printStackTrace();
}
}
The line that crashes is this one:
reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
I understand that this is because "is" is null and I should have to catch this case so avoiding the app to crash (I will fix this in my next version).
EDIT 3: You are right, greenapps, I will check if is is null before using it and in other case I will not use it.
And I understand that "is" is null because there is a IOException doing this:
totalSize = fileToParse.length();
is = new BufferedInputStream(new FileInputStream(fileToParse));
EDIT 4: Of course, if this gives me a IOEXception I will have to change my code to make a complete different thing.
And I can't find on Internet the reasons so these 2 lines of code could throw a IOException.
In think the fileToParse is ok, or at least is not null, because I pass this "files" list to an adapter to show their files names with files.get(i).getName() and the name is shown properly.
I have to add that the file to process is very large and has sensitive personal data so the user can't send it to me so I can test with it.
None of my files give me that error and without the problematic file it's very difficult to me to trace the problem so I have to guess. Any idea of what reasons could cause this error?
Thank you very much and kind regards!
EDIT 5: Following ctarabusi suggestion I've changed my parseFile method to this:
public void parseFile(File fileToParse)
{
long totalSize = 0;
InputStream is = null;
try {
totalSize = fileToParse.length();
is = new BufferedInputStream(new FileInputStream(fileToParse));
BufferedReader reader = null;
reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String line = "";
StringTokenizer st = null;
while ((line = reader.readLine()) != null) {
// Here I parse the file
}
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Error parsing file", Toast.LENGTH_LONG).show();
e.printStackTrace();
} finally {
if(is != null)
{
try
{
is.close();
}
catch (IOException e)
{
Log.e("", e.getMessage(), e);
}
}
}
}
My tests are working properly again, but the user has told me that he sees the "Error parsing file" message, so it's failing yet.
What else could I check?