Операції читання та записи у файл є стандартним функціоналом будь-яких додатків, які ведуть журналування подій, роботу з файлами, аж до передачі даних через мережу. У цій статті розглянемо методи запису у файли інформації та читання з файлу записаного рядка.
Структура проекта
Естетичних змін стандартних кнопок або ListView в даному уроці не буде проводитися, оскільки ми будемо працювати з тим, що приховано від очей користувача, а саме працювати з файлами.
Вся структура проекту відповідно складається цього разу лише з одного класу: MainActivity
Також у проекті присутні такі файли ресурсів:
- діяльність_main.xml
- strings.xml
- styles.xml - у цьому файлі відсутні будь-які зміни, що стосуються проекту.
Крім цього, внесено зміни до файлу AndroidManifest.xml. У файлі необхідно додати наступні два рядки. Це дозволи для програми - робити операції читання і записи із зовнішнім накопичувачем (тобто SD Card телефону). Проте з погляду операційної систем цей накопичувач (тобто SD Card) є зовнішнім накопичувачем. У цій статті не розглядатиметься варіант роботи з істинно внутрішнім накопичувачем.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ru.evileg.workwithfiles" > <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ... </manifest>
Формування розмітки програми
діяльність_main.xml
Розмітка основної активіті, в якій виконуватиметься робота нашої програми. У цій розмітці присутні лише дві кнопки (Button) і текстове поле (TextView), в яке ми виводитимемо інформацію збережену у файлі.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:background="#ffffff" android:orientation="vertical" tools:context=".MainActivity"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/write_file" android:id="@+id/buttonWrite" android:layout_gravity="center_horizontal" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/read_file" android:id="@+id/buttonRead" android:layout_gravity="center_horizontal" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/textView" android:textSize="26sp" android:layout_gravity="center_horizontal" /> </LinearLayout>
strings.xml
Файл ресурсів тексту в Android. Підготовка всіх рядків, які застосовуються у Вашому Додатку в даному файлі, є не тільки гарним тоном, але обов'язковою умовою для розробки якісного Програми. Оскільки, якщо ви будете дисциплінувати себе, зберігати всю подібну інформацію в даному файлі, то згодом це окупиться, коли ви будете робити переклад Програми іншими мовами. Тим більше, що Android Studio має зручний функціонал для цього.
<resources> <string name="app_name">Work With Files</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="write_done">Запись выполнена</string> <string name="write_file">Записать данные в файл</string> <string name="read_file">Считать данные из файла</string> </resources>
styles.xml
У цьому файлі немає змін, що стосуються проекту. Але при створенні проекту стандартна тема оформлення не рендерує Android Studio. Видається помилка під час перегляду та в режимі дизайну. Щоб цього уникнути, пропишіть наступну інформацію замість старої.
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Base.Theme.AppCompat.Light"/> </resources>
Основний клас проекту - MainActivity.java
Сьогодні у цьому класі сконцентрований весь програмний код. У цьому класі виробляється формування зовнішнього вигляду головної активіті, і навіть організується робота з файлами.
package ru.evileg.workwithfiles; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; public class MainActivity extends AppCompatActivity implements View.OnClickListener { /* * Создаем постоянные константы для удобства работы, * объявляем TextView, который должен быть доступен в нескольких методах класса */ private static final String fileName = "hello.txt"; private static final String text = "Hello World"; private static TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* * Объявляем и инциализируем Кнопки (Button), * а также инициализируем TextView * Также в активити имплементирован метод слушателя событий нажатия, * то есть OnClickListener, который привязывается к кнопкам */ textView = (TextView) this.findViewById(R.id.textView); Button buttonWrite = (Button) this.findViewById(R.id.buttonWrite); Button buttonRead = (Button) this.findViewById(R.id.buttonRead); buttonWrite.setOnClickListener(this); buttonRead.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } /* * Обработчик нажатий кнопок. Нажатая кнопка определяется по её ID через метод getID() */ @Override public void onClick(View v) { switch (v.getId()){ case R.id.buttonWrite: writeFile(); break; case R.id.buttonRead: readFile(); break; default: break; } } private void writeFile() { try { /* * Создается объект файла, при этом путь к файлу находиться методом класcа Environment * Обращение идёт, как и было сказано выше к внешнему накопителю */ File myFile = new File(Environment.getExternalStorageDirectory().toString() + "/" + fileName); myFile.createNewFile(); // Создается файл, если он не был создан FileOutputStream outputStream = new FileOutputStream(myFile); // После чего создаем поток для записи outputStream.write(text.getBytes()); // и производим непосредственно запись outputStream.close(); /* * Вызов сообщения Toast не относится к теме. * Просто для удобства визуального контроля исполнения метода в приложении */ Toast.makeText(this, R.string.write_done, Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); } } private void readFile() { /* * Аналогично создается объект файла */ File myFile = new File(Environment.getExternalStorageDirectory().toString() + "/" + fileName); try { FileInputStream inputStream = new FileInputStream(myFile); /* * Буфферезируем данные из выходного потока файла */ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); /* * Класс для создания строк из последовательностей символов */ StringBuilder stringBuilder = new StringBuilder(); String line; try { /* * Производим построчное считывание данных из файла в конструктор строки, * Псоле того, как данные закончились, производим вывод текста в TextView */ while ((line = bufferedReader.readLine()) != null){ stringBuilder.append(line); } textView.setText(stringBuilder); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } } }
Підсумок
Якщо в процесі вивчення матеріалу не виникло жодних проблем і помилок, то після натискання кнопки запису у файл відбудеться створення нового файлу і буде здійснено запис рядка "Hello World". При натисканні кнопки читання буде виведена інформація, збережена в текстовому файлі. Процес показаний на скріншотах нижче.
Після натискання кнопки виконується запис у файл інформації
Запис у файл
Читання з файлу виконується за натисканням відповідної кнопки. При цьому у TextView виводиться текст
Створений файл hello.txt у файловому менеджері
Как я понял данное приложение сохраняет текст в один единственный файл - hello.txt. Хотел бы узнать как можно реализовать функцию создания новый текстовых файлов и их переименования, т.е после нажатия на кнопку сохранения будет создаваться новый текстовый файл, пользователь будет выбирать куда не телефоне его сохранить и сам же вводит имя файла. А так же как реализовать функцию выбора из каталога файлов, т. е при нажатие на кнопку "считать из файла" открывалась бы папка в которой у пользователя находятся другие текстовые документы и он мог их редактировать последующего редактирования.
эххх... как это было давно и не правда )))) я с тех пор (через пару месяцев после этой статьи +-) на Java и не писал больше.
Вот если меня накроет не по-детски и я всё-таки начну писать сравнительные статьи Android: Java vs Qt , вот тогда что-нибудь интересное и вывалится на эту тему. А так пока... даже не знаю, что Вам ответить.