Я только что выпустил приложение для 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")));
Я понимаю, что это потому, что «is» имеет значение null, и мне нужно будет поймать этот случай, чтобы избежать сбоя приложения (я исправлю t его в моей следующей версии).
РЕДАКТИРОВАТЬ 3: Вы правы, greenapps, я проверю, имеет ли значение null перед его использованием, а в другом случае я его не буду использовать.
И я понимаю, что «есть» равно нулю, потому что есть IOException делает это:
totalSize = fileToParse.length();
is = new BufferedInputStream(new FileInputStream(fileToParse));
EDIT 4: Конечно, если это дает мне IOException мне придется изменить свой код, чтобы сделать совершенно другой предмет.
И я не могу найти в Интернете причины, поэтому эти 2 строки кода могут вызывать исключение IOException.
Думаю, что fileToParse в порядке или по крайней мере не является нулевым, потому что я передаю этот список «файлам» адаптеру, чтобы показать имена своих файлов с помощью files.get (i) .getName(), и показано имя должным образом.
Я должен добавить, что файл для обработки очень велик и имеет конфиденциальные личные данные, поэтому пользователь не может отправить его мне, чтобы я мог с ним проверить.
Ни один из моих файлов не дает мне эту ошибку и без проблемного файла мне очень сложно отслеживать проблему, поэтому я должен угадать. Любая идея о том, какие причины могут вызвать эту ошибку?
Большое спасибо и с уважением!
EDIT 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», этот параметр необходим. Кроме того, вы можете попытаться установить точки останова на своих линиях назначения и проверить, имеют ли ваши переменные ожидаемые значения. – localhorst
Привет! У меня есть разрешение WRITE_EXTERNAL_STORAGE в манифесте Android, поэтому я думаю, что все в порядке. – Wonton
«Поймите, что это потому, что« есть », и мне нужно поймать этот случай, чтобы избежать прихода приложения». Нет, вы должны проверить, имеет ли значение null, прежде чем использовать его. И не используйте его, если это так. – greenapps