В этом уроке:
- работаем с файлами
Работа с файлами в Android не сильно отличается от таковой в Java. В этом уроке рассмотрим, как записать/прочесть файл во внутреннюю память и на SD-карту.
Создадим проект:
Project name: P0751_Files
Build Target: Android 2.3.3
Application name: Files
Package name: ru.startandroid.develop.p0751files
Create Activity: MainActivity
Заполним strings.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">P0751_Files</string> <string name="write_file">Записать файл</string> <string name="read_file">Прочесть файл</string> <string name="write_file_sd">Записать файл на SD</string> <string name="read_file_sd">Прочесть файл с SD</string> </resources>
Рисуем экран main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/btnWrite" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/write_file" android:onClick="onclick"> </Button> <Button android:id="@+id/btnRead" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/read_file" android:onClick="onclick"> </Button> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/btnWriteSD" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/write_file_sd" android:onClick="onclick"> </Button> <Button android:id="@+id/btnReadSD" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/read_file_sd" android:onClick="onclick"> </Button> </LinearLayout> </LinearLayout>
4 кнопки, смысл которых понятен по тексту на них.
MainActivity.java:
package ru.startandroid.develop.p0751files; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; public class MainActivity extends Activity { final String LOG_TAG = "myLogs"; final String FILENAME = "file"; final String DIR_SD = "MyFiles"; final String FILENAME_SD = "fileSD"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void onclick(View v) { switch (v.getId()) { case R.id.btnWrite: writeFile(); break; case R.id.btnRead: readFile(); break; case R.id.btnWriteSD: writeFileSD(); break; case R.id.btnReadSD: readFileSD(); break; } } void writeFile() { try { // отрываем поток для записи BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( openFileOutput(FILENAME, MODE_PRIVATE))); // пишем данные bw.write("Содержимое файла"); // закрываем поток bw.close(); Log.d(LOG_TAG, "Файл записан"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } void readFile() { try { // открываем поток для чтения BufferedReader br = new BufferedReader(new InputStreamReader( openFileInput(FILENAME))); String str = ""; // читаем содержимое while ((str = br.readLine()) != null) { Log.d(LOG_TAG, str); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } void writeFileSD() { // проверяем доступность SD if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { Log.d(LOG_TAG, "SD-карта не доступна: " + Environment.getExternalStorageState()); return; } // получаем путь к SD File sdPath = Environment.getExternalStorageDirectory(); // добавляем свой каталог к пути sdPath = new File(sdPath.getAbsolutePath() + "/" + DIR_SD); // создаем каталог sdPath.mkdirs(); // формируем объект File, который содержит путь к файлу File sdFile = new File(sdPath, FILENAME_SD); try { // открываем поток для записи BufferedWriter bw = new BufferedWriter(new FileWriter(sdFile)); // пишем данные bw.write("Содержимое файла на SD"); // закрываем поток bw.close(); Log.d(LOG_TAG, "Файл записан на SD: " + sdFile.getAbsolutePath()); } catch (IOException e) { e.printStackTrace(); } } void readFileSD() { // проверяем доступность SD if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { Log.d(LOG_TAG, "SD-карта не доступна: " + Environment.getExternalStorageState()); return; } // получаем путь к SD File sdPath = Environment.getExternalStorageDirectory(); // добавляем свой каталог к пути sdPath = new File(sdPath.getAbsolutePath() + "/" + DIR_SD); // формируем объект File, который содержит путь к файлу File sdFile = new File(sdPath, FILENAME_SD); try { // открываем поток для чтения BufferedReader br = new BufferedReader(new FileReader(sdFile)); String str = ""; // читаем содержимое while ((str = br.readLine()) != null) { Log.d(LOG_TAG, str); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
В onclick обрабатываем нажатия 4-х кнопок и вызываем соответствующие методы.
writeFile – запись файла во внутреннюю память. Используется метод openFileOutput, который на вход берет имя файла и режим записи: MODE_PRIVATE – файл доступен только этому приложению, MODE_WORLD_READABLE – файл доступен для чтения всем, MODE_WORLD_WRITEABLE - файл доступен для записи всем, MODE_APPEND – файл будет дописан, а не начат заново.
readFile – чтение файла из внутренней памяти. Используем метод openFileInput, принимающий на вход имя файла. Здесь и в методе записи внутреннего файла вы можете задать только имя файла, а каталог для ваших файлов вам уже выделен.
writeFileSD – запись файла на SD. Используем метод getExternalStorageState для получения состояния SD-карты. Здесь можно посмотреть какие бывают состояния. Нам нужно MEDIA_MOUNTED – когда SD-карта вставлена и готова к работе. Далее мы получаем путь к SD-карте (метод getExternalStorageDirectory), добавляем свой каталог и имя файла, создаем каталог и пишем данные в файл.
readFileSD – чтение файла с SD. Все аналогично предыдущему методу, только файл не пишем, а читаем.
Осталось в манифест добавить разрешение на работу с файлами на SD - android.permission.WRITE_EXTERNAL_STORAGE.
Все сохраним и запустим. Видим экран с 4-мя кнопками:
Внутренняя память
Жмем кнопку Записать файл. Видим в логе:
Файл записан
Проверим. Идем в File Explorer (Window > Show View > Other > Android > File Explorer) и открываем там папку data/data/ru.startandroid.develop.p0751files/files и видим там наш файл file.
Возвращаемся в эмулятор. Жмем Прочесть файл и в логе видим:
Содержимое файла
Это тот текст, который мы записывали в файл.
SD карта
Теперь жмем Записать файл на SD.
В логе видим:
Файл записан на SD: /mnt/sdcard/MyFiles/fileSD
Проверяем. Идем в FileExplorer и открываем там папку mnt/sdcard/MyFiles/ а в ней файл fileSD.
Возвращаемся в эмулятор и жмем кнопку Прочесть файл с SD. В логе видим:
Содержимое файла на SD
Этот текст мы и записывали.
mnt/sdcard - обычно этот путь ведет к содержимому SD-карты. Возможно у вас он будет другой.
В общем, при работе с файлами на SD вы используете стандартные java механизмы. А при работе с внутренним хранилищем для удобства можно использовать методы-оболочки от Activity:
openFileOutput – открыть файл на запись
openFileInput – открыть файл на чтение
deleteFile – удалить файл
И есть метод getFilesDir – возвращает объект File, соответствующий каталогу для файлов вашей программы. Используйте его, чтобы работать напрямую, без методов-оболочек.
Подробности работы в java с файловой системой я здесь описывать не буду. На нашем форуме пользователь SKR сделал отличную памятку по работе с файлами. Скорее всего, вы найдете там все что нужно.
Если у вас проверка SD-карты показывает, что карта недоступна (см. лог), то убедитесь в свойствах AVD, что у вас для SDCard указан Size или File. Если указаны, то попробуйте перезапустить AVD.
На следующем уроке:
- создаем экран с вкладками
- используем иконку в названии вкладки
- используем обработчик перехода между вкладками
Присоединяйтесь к нам в Telegram:
- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня