Урок 75. Хранение данных. Работа с файлами.


В этом уроке:

- работаем с файлами

Работа с файлами в Android не сильно отличается от таковой в Java. В этом уроке рассмотрим, как записать/прочесть файл во внутреннюю память и на флэшку.


Создадим проект:

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.


На следующем уроке:

- создаем экран с вкладками
- используем иконку в названии вкладки
- используем обработчик перехода между вкладками