4

Я только что выпустил приложение для 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); 
      } 
     } 
    } 
} 

Мои тесты работают должным образом снова, но пользователь сказал мне, что он видит «файл Ошибка синтаксического анализа» сообщение , так что это еще не удается.

Что еще я могу проверить?

+0

ли вы указать «READ_EXTERNAL_STORAGE» разрешение в манифесте? Если ваш клиент использует телефон с API 19+, и вы не используете «WRITE_EXTERNAL_STORAGE», этот параметр необходим. Кроме того, вы можете попытаться установить точки останова на своих линиях назначения и проверить, имеют ли ваши переменные ожидаемые значения. – localhorst

+0

Привет! У меня есть разрешение WRITE_EXTERNAL_STORAGE в манифесте Android, поэтому я думаю, что все в порядке. – Wonton

+0

«Поймите, что это потому, что« есть », и мне нужно поймать этот случай, чтобы избежать прихода приложения». Нет, вы должны проверить, имеет ли значение null, прежде чем использовать его. И не используйте его, если это так. – greenapps

ответ

0

Возможно, проблема заключается в том, что вы не закрываете свои входные потоки. Файловые дескрипторы и потоки - это ограниченные ресурсы, и важно освободить их, когда вы закончите с ними.

Обычно это делается в конце концов блок, как:

InputStream inputStream = null; 
try 
{ 
    ... use your input stream 
} 
catch (IOException e) 
{ 
    Log.e(TAG, e.getMessage(), e); 
} 
finally 
{ 
    if (inputStream != null) 
    { 
     try 
     { 
      inputStream.close(); 
     } 
     catch (IOException e) 
     { 
      Log.e(TAG, e.getMessage(), e); 
     } 
    } 
} 
+0

Это может быть проблемой, потому что я не закрываю этот входной поток. Я попробую это и дам вам знать. В любом случае, не закрывая этот входной поток, может возникнуть проблема, даже если в этом приложении не было открыто ни одного другого входного потока? – Wonton

 Смежные вопросы

  • Нет связанных вопросов^_^