Попытка создать файл в Android: открыть не удалось: EROFS (файловая система только для чтения)

Эта строка:

final FileOutputStream outputStream = new FileOutputStream(name);

приводит к FileNotFoundException с сообщением /2ozjfFQzwv: open failed: EROFS (Read-only file system), где "2ozjfFQzwv" - это то, что я передал в качестве имени файла.

Я пробовал это с разрешением WRITE_INTERNAL_STORAGE и без него. Как создать этот файл для записи?

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


person Drew    schedule 29.03.2013    source источник


Ответы (8)


Я пробовал это с разрешением WRITE_INTERNAL_STORAGE и без него.

В Android нет разрешения WRITE_INTERNAL_STORAGE.

Как создать этот файл для записи?

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

Используйте версию конструктора FileOutputStream, которая принимает объект File. Создайте этот объект File на основе некоторого местоположения, в которое вы можете писать, например:

  • getFilesDir() (звонил на ваш Activity или другой Context)
  • getExternalFilesDir() (звонил на ваш Activity или другой Context)

Последний потребует WRITE_EXTERNAL_STORAGE в качестве разрешения.

Есть ли более простой способ, чем записать его в файл, а затем прочитать из него снова?

Вы можете временно поместить его в статический элемент данных.

потому что у многих людей нет слотов для SD-карт

"Слоты для SD-карт" не имеют значения, по большому счету. 99% пользователей Android-устройств будут иметь внешнее хранилище — исключением будут устройства старше 4 лет, на которых пользователь извлек свою SD-карту. Устройства, выпущенные с середины 2010 года, имеют внешнее хранилище как часть встроенной флэш-памяти, а не как съемный носитель.

person CommonsWare    schedule 29.03.2013
comment
+1 за getFilesDir(), спасибо new BufferedWriter(new FileWriter(getFilesDir() + FILENAME)); - person Owen B; 23.12.2013
comment
Старые устройства? Насколько я узнал из своего Nexus 7 2013 года, он не поддерживает SD-карту... то же самое касается Nexus 10 и, возможно, других Nexi. - person PawelP; 28.12.2013
comment
@PawełParadowski: Все устройства серии Nexus имеют внешнее хранилище. У них нет съемного хранилища. Внешнее хранилище не означает съемное хранилище. - person CommonsWare; 31.12.2013
comment
Вы определенно правы, я должен был внимательно прочитать ваш пост и подумать дважды. - person PawelP; 31.12.2013
comment
Для любых других посетителей из будущего объяснение, представленное в документах, заключается в том, что getExternalFilesDir будет отдавать предпочтение съемному хранилищу, но Environment.isExternalStorageEmulated(File) может определить, является ли это просто точкой монтирования для отдельного внутреннего раздела в API 21+. - person Abandoned Cart; 30.01.2019

попробуйте использовать разрешение WRITE_EXTERNAL_STORAGE Вы должны использовать это независимо от того, есть ли внешняя карта или нет.

Это хорошо работает для меня:

path = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_MOVIES);
File file = new File(path, "/" + fname);

и помещает мои файлы в соответствующую папку

person Martin    schedule 29.03.2013
comment
Starting in API level 19, this permission is not required to read/write files in your application-specific directories returned by getExternalFilesDir(String) and getExternalCacheDir(). developer.android.com/reference/android/ - person androidguy; 24.01.2018

Добавление

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

в манифесте и с использованием того же, что и у Мартина:

path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES); 
File file = new File(path, "/" + fname);

Это сработало.

person nobjta_9x_tq    schedule 22.04.2014
comment
От dev.android: Однако, если ваше приложение использует разрешение WRITE_EXTERNAL_STORAGE, то оно неявно также имеет разрешение на чтение из внешнего хранилища. - person IlyaEremin; 22.09.2014
comment
@ilyaEremin - правда - person Martin; 06.09.2016

Вот простой пример от разработчика Android.

По сути, вы можете записать файл во внутреннюю память следующим образом:

String FILENAME = "hello_file";
String string = "hello world!";

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
person Xuan Wu    schedule 29.03.2013

Как уже упоминалось, приложение на Android не может записывать файл в какую-либо папку внутреннего хранилища, кроме своего собственного частного хранилища (которое находится под /data/data/PACKAGE_NAME ).

Вы должны использовать API, чтобы получить правильный путь, разрешенный для вашего приложения.

прочитайте это .

person android developer    schedule 29.03.2013

Чтобы использовать внутреннее хранилище для приложения, вам не нужно разрешение, но вам может потребоваться использовать: File directory = getApplication().getCacheDir();, чтобы получить разрешенный каталог для приложения.

Или:
getCashDir(); ‹-- должно работать
context.getCashDir(); (если в широковещательном приемнике)
getDataDir(); ‹--Api 24

person Chuck    schedule 13.09.2019

Google ограничил доступ на запись к внешней SD-карте. В API 19 есть инфраструктура под названием Storage Access Framework, которая позволяет вам настраивать «контракты», чтобы разрешить доступ для записи.

Для получения дополнительной информации:

Android - Как использовать новый Storage Access Framework для копирования файлов на внешнюю SD-карту

person Theo    schedule 27.03.2017

Если кто-то получает это при модульном/инструментальном тестировании, убедитесь, что вы вызываете getFilesDir() в контексте приложения, а не в контексте теста. то есть использовать:

Context appContext = getInstrumentation().getTargetContext().getApplicationContext();

нет

Context appContext = InstrumentationRegistry.getContext;
person Maverick Meerkat    schedule 04.03.2019