我刚刚发布了一个Android应用程序,它解析本地文件并对数据进行一些处理。 几天前,我的一位客户向我报告了一个错误,每次他尝试处理他的文件时,应用程序崩溃。BufferedInputStream或FileInputStream IOException
这是他送我的错误日志:
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)
而与此相关的代码是这样的:
// 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();
}
}
的崩溃行是这一个:
reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
我明白,这是因为“是”是空的,我应该抓住这种情况,以避免应用程序崩溃(我将修复t他在我的下一个版本)。
编辑3:你是对的,greenapps,我会检查是否为null之前使用它,在其他情况下,我不会使用它。
而且据我所知,“是”为空,因为有一个IOException异常这样做:
totalSize = fileToParse.length();
is = new BufferedInputStream(new FileInputStream(fileToParse));
编辑4:当然,如果这给了我一个IOException异常我将不得不改变我的代码,使一个完成不同的事情。
而我无法在Internet上找到原因,因此这两行代码可能会抛出IOException。
在认为fileToParse是好的,或至少不是空的,因为我将这个“文件”列表传递给适配器以显示他们的文件名与files.get(i).getName()和名称显示正常。
我不得不补充说,要处理的文件非常大,并且具有敏感的个人数据,因此用户无法将其发送给我,因此我可以使用它进行测试。
我的文件都没有给我这个错误,没有问题的文件,我很难跟踪这个问题,所以我必须猜测。有什么理由可能导致这个错误?
非常感谢您的问候!
编辑5:继ctarabusi建议,我已经改变了我parseFile方法是:
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);
}
}
}
}
我的测试是正常工作了,但用户告诉我,他看到了“解析文件时出错”消息,所以它还没有失败。
我还能检查什么?
你指定你的清单里面的“READ_EXTERNAL_STORAGE”权限?如果您的客户使用带有API 19+的手机,并且不使用“WRITE_EXTERNAL_STORAGE”,则需要此选项。 此外,您可以尝试在您的赋值行和chech中设置断点,以确定变量是否具有预期值。 – localhorst
嗨!我在Android清单中拥有WRITE_EXTERNAL_STORAGE权限,所以我想这没问题。 – Wonton
'明白这是因为“是”是空的,我应该抓住这种情况,以避免应用程序崩溃'。不,你应该在使用它之前检查是否为空。如果是的话,不要使用它。 – greenapps