Читання та збереження файлів
Робота з налаштуваннями рівня activity і програми дозволяє зберігати невеликі дані окремих типів (string, int), але для роботи з більшими масивами даних, такими як графічні файли, файли мультимедіа тощо, нам доведеться звертатися до файлової системи.
ОС Android побудована на основі Linux. Цей факт знаходить своє відображення в роботі з файлами. Так, у шляхах до файлів в Linux використовується коса риска /, а не зворотна риска \ (як у Windows). А всі назви файлів і каталогів є чутливими до регістру, тобто "data" — це не те ж саме, що і "Data".
Програма Android зберігає свої дані в каталозі /data/data/<назва_пакета>/ і, як правило, відносно цього каталогу буде йти робота.
Для роботи з файлами абстрактний клас android.content.Context визначає низку методів:
- boolean deleteFile (String name): видаляє певний файл.
- String fileList (): отримує всі файли, які містяться в підкаталозі
/filesкаталогу програми. - File getCacheDir(): отримує посилання на підкаталог
cacheв каталозі програми. - File getDir(String dirName, int mode): отримує посилання на підкаталог в каталозі програми, якщо такого підкаталога немає, то він створюється.
- File getExternalCacheDir(): отримує посилання на папку
/cacheзовнішньої файлової системи пристрою. - File getExternalFilesDir(String type): отримує посилання на каталог
/filesзовнішньої файлової системи пристрою. - File getFileStreamPath(String filename): повертає абсолютний шлях до файлу в файловій системі.
- FileInputStream openFileInput(String filename): відкриває файл для читання.
- FileOutputStream openFileOutput (String name, int mode): відкриває файл для запису.
Усі файли, які створюються і редагуються в програмі, зазвичай зберігаються в підкаталозі /files в каталозі програми.
Для безпосереднього читання і запису файлів застосовуються також стандартні класи Java з пакету java.io.
Отже, застосуємо функціонал читання-запису файлів у додатку. Нехай у нас буде така примітивна розмітка layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/editor"
android:layout_width="0dp"
android:layout_height="0dp"
android:textSize="18sp"
android:gravity="start"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/save_text"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/save_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="saveText"
android:text="Сохранить"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/text"
app:layout_constraintTop_toBottomOf="@id/editor" />
<TextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="start"
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@+id/open_text"
app:layout_constraintTop_toBottomOf="@+id/save_text" />
<Button
android:id="@+id/open_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="openText"
android:text="Открыть"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text" />
</androidx.constraintlayout.widget.ConstraintLayout>
Поле EditText призначене для введення тексту, а TextView - для виведення раніше збереженого тексту. Для збереження і відновлення тексту додано дві кнопки.
Тепер у коді Activity пропишемо обробники кнопок зі збереженням і читанням файлу:
package com.example.filesapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private static final String FILE_NAME = "content.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Збереження тексту у файл
public void saveText(View view) {
EditText editor = findViewById(R.id.editor);
String text = editor.getText().toString();
// Використовуємо try-with-resources для автоматичного закриття потоку
try (FileOutputStream fos = openFileOutput(FILE_NAME, MODE_PRIVATE)) {
fos.write(text.getBytes());
showToast("Файл збережено");
} catch (IOException e) {
showToast("Помилка при збереженні: " + e.getMessage());
}
}
// Відкриття тексту з файлу
public void openText(View view) {
TextView textView = findViewById(R.id.text);
// Використовуємо try-with-resources для автоматичного закриття потоку
try (FileInputStream fin = openFileInput(FILE_NAME)) {
byte[] bytes = new byte[fin.available()];
fin.read(bytes);
String text = new String(bytes);
textView.setText(text);
} catch (IOException e) {
showToast("Помилка при відкритті: " + e.getMessage());
}
}
// Метод для відображення повідомлень Toast
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
варіант 2:
package com.example.filesapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private static final String FILE_NAME = "content.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Збереження тексту у файл з використанням BufferedWriter
public void saveText(View view) {
EditText editor = findViewById(R.id.editor);
String text = editor.getText().toString();
// Використовуємо try-with-resources для автоматичного закриття потоку
try (BufferedWriter writer = new BufferedWriter(new FileWriter(getFileStreamPath(FILE_NAME)))) {
writer.write(text);
showToast("Файл збережено");
} catch (IOException e) {
showToast("Помилка при збереженні: " + e.getMessage());
}
}
// Відкриття тексту з файлу з використанням BufferedReader
public void openText(View view) {
TextView textView = findViewById(R.id.text);
StringBuilder stringBuilder = new StringBuilder();
// Використовуємо try-with-resources для автоматичного закриття потоку
try (BufferedReader reader = new BufferedReader(new FileReader(getFileStreamPath(FILE_NAME)))) {
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
textView.setText(stringBuilder.toString());
} catch (IOException e) {
showToast("Помилка при відкритті: " + e.getMessage());
}
}
// Метод для відображення повідомлень Toast
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
варіант №3
package com.example.filesapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
public class MainActivity extends AppCompatActivity {
private static final String FILE_NAME = "content.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Збереження тексту у файл з використанням NIO (Java NIO)
public void saveText(View view) {
EditText editor = findViewById(R.id.editor);
String text = editor.getText().toString();
// Створюємо шлях до файлу
Path path = getFileStreamPath(FILE_NAME).toPath();
try {
// Записуємо текст у файл, використовуючи NIO (вказуємо кодування)
Files.write(path, text.getBytes(StandardCharsets.UTF_8));
showToast("Файл збережено");
} catch (IOException e) {
showToast("Помилка при збереженні: " + e.getMessage());
}
}
// Відкриття тексту з файлу з використанням NIO (Java NIO)
public void openText(View view) {
TextView textView = findViewById(R.id.text);
// Створюємо шлях до файлу
Path path = getFileStreamPath(FILE_NAME).toPath();
try {
// Зчитуємо вміст файлу в рядок за допомогою NIO
String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
textView.setText(content);
} catch (IOException e) {
showToast("Помилка при відкритті: " + e.getMessage());
}
}
// Метод для відображення повідомлень Toast
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
При натисканні на кнопку збереження буде створюватися потік виводу:
FileOutputStream fos = openFileOutput(FILE_NAME, MODE_PRIVATE);
У цьому випадку введений текст буде зберігатися у файл "content.txt". При цьому буде використовуватися режим MODE_PRIVATE.
Система дозволяє створювати файли з двома різними режимами:
- MODE_PRIVATE: файли можуть бути доступні тільки власнику програми (режим за замовчуванням).
- MODE_APPEND: дані можуть бути додані в кінець файлу.
Тому в даному випадку, якщо файл "content.txt" вже існує, він буде перезаписаний. Якщо ж потрібно було б дописати в файл, тоді слід використовувати режим MODE_APPEND:
FileOutputStream fos = openFileOutput(FILE_NAME, MODE_APPEND);
Для читання файлу застосовується потік вводу:
FileInputStream fin = openFileInput(FILE_NAME);
У підсумку після натискання кнопки збереження весь текст буде збережено у файлі /data/data/назва_пакета/files/content.txt
Де фізично знаходиться створений файл? Щоб побачити його на під'єднаному пристрої перейдемо в Android Stud у меню до пункту View -> Tool Windows -> Device File Explorer
Після цього відкриється вікно Device File Explorer для перегляду файлової системи пристрою. І в папці data/data/[назва_пакета_додатка]/files ми зможемо знайти збережений файл.

Методи openFileOutput та openFileInput — це методи Android, що дозволяють працювати з файлами, які зберігаються в внутрішньому сховищі додатку. Це частина специфічного API для роботи з файлами в Android. Вони використовуються для збереження та зчитування даних, що зберігаються тільки для поточного додатка, і вони не доступні іншим додаткам або користувачам.
Основні характеристики:
- Внутрішнє сховище (Internal Storage):
- Файли, створені за допомогою цих методів, зберігаються в приватній частині внутрішнього сховища вашого додатку. Це означає, що тільки ваш додаток має доступ до цих файлів.
- Вони не доступні іншим додаткам або користувачам.
- Файли, збережені через ці методи, не видимі в системному файловому менеджері.
- Автоматичне керування простором:
- Android автоматично видаляє ці файли, коли додаток видаляється з пристрою.
- Це зручно для зберігання даних, які не потребують постійного доступу або синхронізації з іншими додатками.
- Використання для зберігання невеликих даних:
- Ці методи зазвичай використовуються для збереження невеликих файлів, таких як налаштування, журнали або тимчасові файли, які не вимагають доступу ззовні.