Почему когда-то он выбрасывает FileNotFoundException
Код работает большую часть времени, но некоторое время он выдает исключение. Не удалось выяснить, что может вызвать это.
Что происходит, это создать файл в
/storage/emulated/0/Download/theFileName.jpg
и записывать в него данные (из исходных файлов, которые существуют), но получили исключение "файл не существует" для вновь созданного файла.
(он имеет uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE", and uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE
"в манифесте).
File sourceFile = new File(theSourceFileFullPath);
if (sourceFile.exists()) {
File downloadDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
String downloadPath = downloadDirectory.getPath();
String newFilePath = (downloadPath + "/" + fileName);
File newFile = new File(newFilePath);
try {
FileInputStream in = new FileInputStream(sourceFile);
// ava.io.FileNotFoundException:
// /storage/emulated/0/Download/theFileName.jpg: open failed: ENOENT (No such file or directory)
// exception at this line
FileOutputStream out = new FileOutputStream(newFile);
//......
} catch (Exception e) {}
}
Ответы
Ответ 1
Я могу думать о следующих возможных причинах такого поведения:
- Новый файл не может быть создан просто потому, что на SD-карте нет свободного места. В следующий раз, когда вы столкнетесь с этой проблемой, попробуйте посмотреть, есть ли у вас хотя бы какое-то доступное пространство через диспетчер файлов или Настройки → Хранение. Я сомневаюсь, что вы можете что-то сделать, если это произойдет на вашем пользовательском устройстве.
- SD-карта недоступна из-за сбоя операционной системы или физически не подключена, поэтому файл не может быть создан. Еще раз - вы ничего не можете с этим поделать, кроме как показать
Toast
сообщение об ошибке.
- Как вы создаете часть
fileName
вашего пути к файлу? Иногда файлы не могут быть созданы, потому что имя файла содержит неподдерживаемые (этим конкретным устройством) символы. Например. У меня HTC Desire X с Android 4.1.2, который не может создавать файлы с кодом, похожим на ваш, если имя файла содержит двоеточие. Попробуйте другой способ сгенерировать имя файла и посмотреть, не изменилось ли оно.
-
Вы убедились, что каталог Downloads
существует до создания файла внутри него? Напишите что-то вроде следующего:
if (!downloadDirectory.exists()) {
downloadDirectory.mkdirs();
}
- Разрешение
WRITE_EXTERNAL_STORAGE
считается опасным на Android 6, поэтому он может быть отозван пользователем в любое время. Удостоверьтесь, что пользователь не отозвал это разрешение перед записью в файл.
-
Всегда закрывайте поток ввода-вывода, когда вы закончите работать с ним. Добавьте предложение finally
в блок try-catch и закройте в нем теги in
и out
:
finally {
if (in != null) {
try {
in.close();
} catch (Exception e) { }
}
if (out != null) {
try {
out.close();
} catch (Exception e) { }
}
}
- Последний - и, наконец, у меня нет вариантов.:) Я полагаю, что эта проблема может возникнуть, если вы пишете в тот же файл из нескольких потоков. В этом случае попробуйте синхронизировать доступ к вашему файловому коде.
Ответ 2
В соответствии с Java docs - Класс FileNotFoundException:
public class FileNotFoundException extends IOException
Сигналы о том, что попытка открыть файл, обозначенный указанным именем пути, не удалось.
Это исключение будет выбрано FileInputStream
, FileOutputStream
и RandomAccessFile
, когда файл с указанный pathname
не существует. Он также будет брошен этими конструкторы, если файл существует, но по какой-либо причине недоступно, например, когда делается попытка открыть только для чтения файл для записи.
Чтобы возобновить работу, есть три случая, когда может быть выбрано значение FileNotFoundException
.
- Именованный файл не существует.
- Именованный файл на самом деле является каталогом.
- Именованный файл не может быть открыт для чтения по какой-либо причине.
получилось исключение "файл не существует" для вновь созданного файла.
В вашем коде я не вижу двух вещей
- Удаление файла после успешной записи. Я вообще не шучу. Если бы у меня был класс, похожий на эту и ту ошибку, я бы сделал своего рода тест, который завершился бы с удалением
downlaodDirectory
после копирования содержимого из исходного файла. В этом случае он передаст этот метод или вы получите другую, но более конкретную ошибку - например, по-моему: невозможно удалить файл. При использовании
- Закрытие файла после записи данных. Я также не вижу способ закрыть файлы. В вашем коде кажется, что ваш файл по-прежнему открыт, поэтому вы запускаете снова приложение, и вы получаете эту непредсказуемую ошибку.
Чтобы исправить проблему, просто закройте оба файла после обработки данных с помощью метода file.close()
.
Надеюсь, что это поможет
Ответ 3
-
Проблема может возникнуть из-за способа создания файла:
String downloadPath = downloadDirectory.getPath();
String newFilePath = (downloadPath + "/" + fileName);
File newFile = new File(newFilePath);
Здесь находится опасный код:
String newFilePath = (downloadPath + "/" + fileName);
Вместо этого попробуйте использовать следующий подход:
File newFile = new File(downloadDirectory, fileName);
-
Доступность SD-карты - проверьте следующую документацию
http://developer.android.com/training/basics/data-storage/files.html#WriteExternalStorage.
Возможно, носители не установлены (например, на некоторых старых устройствах
это происходит, когда пользователь подключает устройство к компьютеру через usb) Итак, попробуйте
проверьте, установлен ли носитель:
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
и уведомить пользователя, если нет.
Ответ 4
Я надеюсь, что ваш код для записи данных в файл идеален. Я просто сконцентрирован в вашей проблеме. Я думаю, что есть две возможности получить файл не найден Исключением.
- Некоторое время Имя файла не поддерживается. Некоторый особый символ. Пока вы предоставляете такого рода символы, чтобы указать имя файла в тот момент, файл не был правильно Создан, почему произошла эта ошибка. Поэтому, пожалуйста, убедитесь, что ваше имя файла правильно.
- second - это расширение вашего файла. Если вы не указали, какой файл у вас есть.
здесь У меня есть фрагмент кода. Надеюсь, это поможет решить проблему.
Решение
File file=new File(Environment.getExternalStorageDirectory()+"/"+ConstansClass.FOLDERNAME);
if(!file.exists())
{
file.mkdir();
}
String file=filename.replaceAll("[^a-zA-Z0-9.-]", " ");
yourDir = new File(file, file+".mp3");
if(yourDir.exists())
{
return yourDir;
}
Edit
Я извиняюсь lannf Я не знаю, что именно происходит в вашем коде, но у меня есть один фрагмент кода, который просто загружает mp3 файл из soundcloude и Store в моем локальном хранилище. Я думаю, что он точно такой же, как и ваш require.so я разместите мой код ниже.
@Override
protected File doInBackground(Void... params) {
//File sdCardRoot = Environment.getExternalStorageDirectory()+"/Music";
File file=new File(Environment.getExternalStorageDirectory()+"/"+ConstansClass.FOLDERNAME);
if(!file.exists())
{
file.mkdir();
}
String filename=soundCloudeResponse.getTitle();//.replaceAll("[^a-zA-Z0-9.-]", " ");
yourDir = new File(file, filename+".mp3");
if(yourDir.exists())
{
return yourDir;
}
String url=soundCloudeResponse.getStream_url()+"?"+ConstansClass.SOUNDCLOUDE_CLIENT_ID;
URL u = null;
try {
DebugLog.e("Request Url"+ url);
u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(yourDir));
fos.write(buffer);
fos.flush();
fos.close();
DebugLog.d("Download Complete in On Background");
} catch (MalformedURLException e) {
sucess=false;
e.printStackTrace();
} catch (IOException e) {
sucess=false;
e.printStackTrace();
}
catch (Exception e)
{
sucess=false;
e.printStackTrace();
DebugLog.e("Error ::"+e.getMessage());
}
return yourDir;
}
Я думаю, что вы умный разработчик, поэтому вы можете изменить этот код в соответствии с вашими требованиями.
Лучшее от удачи
Ответ 5
вы не опубликовали все стеки стека исключений, но я нашел точную проблему, разрешенную SO.
java.io.FileNotFoundException: /storage/emulated/0/bimagechooser/1429031333305.jpg: open failed: ENOENT (No such file or directory)
Используйте эту библиотеку image-chooser-library. и необходимо перефакторировать код.
The Guy coomar2841. безусловно, поможет вам. поскольку он часами решает проблему. поэтому экономьте свое время.
Захватили источники com.kbeanie.imagechooser и сбросили их в APP, удалили объявление gradle для библиотеки, и APP должен работать.
просмотрите проблему GitHub
Надеюсь, это сработает для вас.:)
Ответ 6
Там может быть еще одна возможность:
Если одна часть вашего кода пишет файл, а другая читает, тогда будет полезно учесть, что читатель читает до того, как автор заканчивает писать файл.
Вы можете перепроверить этот случай, переведя код в режим отладки. Если там все работает нормально и выдает исключение FileNotFoundException, то, несомненно, это может быть потенциальной причиной этого исключения.
Теперь, как решить:
Вы можете использовать механизм повтора, похожий на приведенный ниже блок кода.
if(!file..exists()){
Thread.sleep(200);}
в вашем коде и измените значение сна в соответствии с вашими потребностями.
Надеюсь, это поможет.!!