14 - Almacenamiento de datos en un archivo de texto en la memoria interna


Otra posibilidad de almacenar datos en nuestro dispositivo Android es el empleo de un archivo de texto que se guardará en el almacenamiento interno del equipo (la otro posibilidad es almacenarlo en una tarjeta SD Card)

Problema 1:

Confeccionar un programa que permita almacenar notas en un control EditText y cuando se presione un botón almacenar los datos del EditText en un archivo de texto llamado "notas.txt".
Cada vez que se ingrese al programa verificar si existe el archivo de textos "notas.txt", proceder a su lectura y almacenamiento de datos en el EditText.

Crear un proyecto en Android Studio y definir como nombre: proyecto016.

Para crear la interfaz visual primero disponemos un botón alineado en la parte inferior del celular y luego de la pestaña "Text Fields" seleccionamos un objeto de la clase EditText ("Multiline Text") y lo disponemos en la parte superior de la pantalla e inicializamos la propiedad background del EditText con el valor #ffff00 (que corresponde con el color amarillo):

Archivos de texto memoria interna

Finalmente procedemos a redimensionar el EditText por medio del mouse y configuramos la propiedad gravity tildando los valores top y left para que los datos que ingresa el operador aparezcan en la parte superior izquierda y no centrados:

Archivos de texto memoria interna

El código fuente de la aplicación:

package ar.com.tutorialesya.proyecto016;

import android.app.Activity;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;


public class MainActivity extends ActionBarActivity {
    private EditText et1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        et1=(EditText)findViewById(R.id.editText);
        String[] archivos = fileList();

        if (existe(archivos, "notas.txt"))
            try {
                InputStreamReader archivo = new InputStreamReader(
                        openFileInput("notas.txt"));
                BufferedReader br = new BufferedReader(archivo);
                String linea = br.readLine();
                String todo = "";
                while (linea != null) {
                    todo = todo + linea + "\n";
                    linea = br.readLine();
                }
                br.close();
                archivo.close();
                et1.setText(todo);
            } catch (IOException e) {
            }
    }


    @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);
    }

    private boolean existe(String[] archivos, String archbusca) {
        for (int f = 0; f < archivos.length; f++)
            if (archbusca.equals(archivos[f]))
                return true;
        return false;
    }

    public void grabar(View v) {
        try {
            OutputStreamWriter archivo = new OutputStreamWriter(openFileOutput(
                    "notas.txt", Activity.MODE_PRIVATE));
            archivo.write(et1.getText().toString());
            archivo.flush();
            archivo.close();
        } catch (IOException e) {
        }
        Toast t = Toast.makeText(this, "Los datos fueron grabados",
                Toast.LENGTH_SHORT);
        t.show();
        finish();
    }
}

Veamos primero como grabamos datos en un archivo de texto. Esto se hace en el método grabar que se ejecuta cuando presionamos el botón "grabar" (recordemos de inicializar la propiedad "onClick" del botón con el valor "grabar"):


    public void grabar(View v) {
        try {
            OutputStreamWriter archivo = new OutputStreamWriter(openFileOutput("notas.txt",Activity.MODE_PRIVATE));

Creamos un objeto de la clase OutputStreamWriter y al constructor de dicha clase le enviamos el dato que retorna el método openFileOutput propio de la clase ActionBarActivity que le pasamos como parámetro el nombre del archivo de texto y el modo de apertura.

Seguidamente si el archivo se creó correctamente procedemos a llamar al método write y le pasamos el String a grabar, en este caso extraemos los datos del EditText:

            archivo.write(et1.getText().toString());

Luego de grabar con el método write llamamos al método flush para que vuelque todos los datos que pueden haber quedado en el buffer y procedemos al cerrado del archivo:

            archivo.flush();
            archivo.close();            

Todo esto está cerrado en un try/catch para verificar si sucede algún error en la apertura del archivo.

Finalmente mostramos un mensaje temporal en pantalla utilizando la clase Toast:


        Toast t=Toast.makeText(this,"Los datos fueron grabados", Toast.LENGTH_SHORT);
        t.show();
        finish();

Para crear un objeto de la clase Toast llamamos al método makeText de la clase Toast y le pasamos la referencia del ActionBarActivity actual, el String a mostrar y el tiempo de duración del mensaje. Con el objeto devuelto por el método makeText procedemos a llamar seguidamente al método show para que se muestre el mensaje.

Es común llamar al método show de la clase Toast en una sola línea como esta:

        Toast.makeText(this,"Los datos fueron grabados", Toast.LENGTH_SHORT).show();

El método onCreate tiene por objetivo verificar si existe el archivo de texto, proceder a su lectura y mostrar su contenido en el EditText.

Primero obtenemos la lista de todos los archivos creados por la Activity. En nuestro ejemplo puede ser cero o uno:

        String []archivos=fileList();

Llamamos a un método que verifica si en el vector de tipo String existe el archivo "notas.txt":

        if (existe(archivos,"notas.txt")) 

En el caso que me retorne true procedemos a crear un objeto de la clase InputStreamReader y al constructor de dicha clase le pasamos el dato devuelto por el método openFileInput:

                InputStreamReader archivo=new InputStreamReader(openFileInput("notas.txt"));

Creamos un objeto de la clase BufferedReader y le pasamos al constructor la referencia del objeto de la clase InputStreamReader:

                BufferedReader br=new BufferedReader(archivo);

Leemos la primer línea del archivo de texto:

                String linea=br.readLine();

Inicializamos un String vacío:

                String todo="";

Mientras el método readLine de la clase BufferedReader devuelva un String:

                while (linea!=null)
                {

Lo concatenamos al String junto a un salto de línea:

                    todo=todo+linea+"\n";

Leemos la próxima línea:

                    linea=br.readLine();
                }

Llamamos al método close de la clase BufferedReader y al del InputStreamReader:

                br.close();
                archivo.close();

Cargamos el EditText con el contenido del String que contiene todos los datos del archivo de texto:

                et1.setText(todo);

El método existe llega un vector de tipo String y otro String a buscar. Dentro de un for verificamos el String a buscar con cada uno de los String del vector, si lo encontramos retornamos true. Si recorre todo el for sin encontrarlo fuera del for retornamos false:

    private boolean existe(String[] archivos,String archbusca)
    {
        for(int f=0;f<archivos.length;f++)
            if (archbusca.equals(archivos[f]))
                return true;
        return false;
    }

Este proyecto lo puede descargar en un zip desde este enlace: proyecto016.zip

Luego de ejecutar el programa podemos entrar al "Android Device Monitor" (podemos ejecutarlo desde el menú del Android Studio: Tools->Android->Android Device Monitor) y localizar en el dispositivo donde se guarda el archivo de texto creado:

Archivos de texto memoria interna Android Device Monitor

Como vemos se crea una carpeta llamada "files" que contiene el archivo creado (si creamos más archivos de texto se almacenarán en esta carpeta)

Problema 2:

Confeccionar un programa para administrar un calendario de actividades diarias. Los nombres de archivos corresponderán a las fechas que ingresamos. Luego cuando consultamos una fecha verificamos si hay un archivo de texto que coincida con dicha fecha.

La interfaz visual a crear será la siguiente:

Archivos de texto memoria interna

Es decir disponemos un "Medium Text" donde dice fecha. Un EditText de tipo "Date" donde se carga la fecha. Luego otro EditText de tipo "Multiline Text" y finalmente un botón.

El código fuente de la aplicación:

package ar.com.tutorialesya.proyecto017;

import android.app.Activity;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;


public class MainActivity extends ActionBarActivity {

    private EditText et1,et2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et1=(EditText)findViewById(R.id.editText);
        et2=(EditText)findViewById(R.id.editText2);
    }


    @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);
    }

     public void grabar(View v) {
            String nomarchivo=et1.getText().toString();
            nomarchivo=nomarchivo.replace('/','-');
            try {
                OutputStreamWriter archivo = new OutputStreamWriter(openFileOutput(
                        nomarchivo, Activity.MODE_PRIVATE));
                archivo.write(et2.getText().toString());
                archivo.flush();
                archivo.close();
            } catch (IOException e) {
            }
            Toast t = Toast.makeText(this, "Los datos fueron grabados",
                    Toast.LENGTH_SHORT);
            t.show();
            et1.setText("");
            et2.setText("");
    }

    public void recuperar(View v) {
        String nomarchivo=et1.getText().toString();
        nomarchivo=nomarchivo.replace('/','-');
        boolean enco=false;
        String[] archivos = fileList();
        for (int f = 0; f < archivos.length; f++)
            if (nomarchivo.equals(archivos[f]))
                enco= true;
        if (enco==true) {
            try {
                InputStreamReader archivo = new InputStreamReader(
                        openFileInput(nomarchivo));
                BufferedReader br = new BufferedReader(archivo);
                String linea = br.readLine();
                String todo = "";
                while (linea != null) {
                    todo = todo + linea + "\n";
                    linea = br.readLine();
                }
                br.close();
                archivo.close();
                et2.setText(todo);
            } catch (IOException e) {
            }
        } else
        {
            Toast.makeText(this,"No hay datos grabados para dicha fecha",Toast.LENGTH_LONG).show();
            et2.setText("");
        }
    }

}

Definimos dos variables que hacen referencia a los EditText donde se cargan la fecha en uno y las actividades de dicho día en el otro:

    private EditText et1,et2;

En el método onCreate obtenemos las referencias de los dos EditText:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et1=(EditText)findViewById(R.id.editText);
        et2=(EditText)findViewById(R.id.editText2);
    }

El método grabar que se ejecuta cuando presionamos el botón grabar (no olvidar de inicializar la propiedad onClick de cada botón con el nombre del método respectivo) tenemos primero que extraer la fecha ingresada en el primer EditText y remplazar las barras de la fecha por guiones ya que no se puede utilizar este caracter dentro de un nombre de archivo en Android:

            String nomarchivo=et1.getText().toString();
            nomarchivo=nomarchivo.replace('/','-');

Creamos un objeto de la clase OutputStreamWriter y al constructor de dicha clase le enviamos el dato que retorna el método openFileOutput propio de la clase ActionBarActivity que le pasamos como parámetro el nombre del archivo de texto y el modo de apertura.

            try {
                OutputStreamWriter archivo = new OutputStreamWriter(openFileOutput(
                        nomarchivo, Activity.MODE_PRIVATE));

Seguidamente si el archivo se creó correctamente procedemos a llamar al método write y le pasamos el String a grabar, en este caso extraemos los datos del EditText:

                archivo.write(et2.getText().toString());

Luego de grabar con el método write llamamos al método flush para que vuelque todos los datos que pueden haber quedado en el buffer y procedemos al cerrado del archivo:

            archivo.flush();
            archivo.close();            

Cada vez que se graba un dato se genera un archivo de texto para dicha fecha, si ya había un archivo con el mismo nombre (es decir la misma fecha) se pisa el anterior.

Desde el "Android Device Monitor" podemos observar todos los archivos de texto que se van creando a medida que registramos actividades en la aplicación que desarrollamos:

Archivos de texto memoria interna

Para recuperar los datos de una determinada fecha se ejecuta el método "recuperar":

  public void recuperar(View v) {
        String nomarchivo=et1.getText().toString();
        nomarchivo=nomarchivo.replace('/','-');
        boolean enco=false;
        String[] archivos = fileList();
        for (int f = 0; f < archivos.length; f++)
            if (nomarchivo.equals(archivos[f]))
                enco= true;
        if (enco==true) {
            try {
                InputStreamReader archivo = new InputStreamReader(
                        openFileInput(nomarchivo));
                BufferedReader br = new BufferedReader(archivo);
                String linea = br.readLine();
                String todo = "";
                while (linea != null) {
                    todo = todo + linea + "\n";
                    linea = br.readLine();
                }
                br.close();
                archivo.close();
                et2.setText(todo);
            } catch (IOException e) {
            }
        } else
        {
            Toast.makeText(this,"No hay datos grabados para dicha fecha",Toast.LENGTH_LONG).show();
            et2.setText("");
        }
    }

Lo primero que hacemos es recuperar del EditText la fecha que ingresó el operador para buscar:

        String nomarchivo=et1.getText().toString();

Remplazamos las barras por guiones (recordemos que grabamos guiones en la carga ya que la barra de una fecha no es un caracter válido en un archivo en Android):

        nomarchivo=nomarchivo.replace('/','-');

Obtenemos la lista de todos los archivos que almacena la aplicación mediante la llamada al método fileList():

        String[] archivos = fileList();

Mediante un for recorremos el vector con los nombres de archivos y los comparamos con la fecha ingresada, en el caso de encontrarlo procedemos a cambiar el estado de una bandera:

        for (int f = 0; f < archivos.length; f++)
            if (nomarchivo.equals(archivos[f]))
                enco= true;

Si la bandera está en true significa que existe el archivo por lo que procedemos a abrirlo, leerlo y cargar el et2 con los datos del archivo:


        if (enco==true) {
            try {
                InputStreamReader archivo = new InputStreamReader(
                        openFileInput(nomarchivo));
                BufferedReader br = new BufferedReader(archivo);
                String linea = br.readLine();
                String todo = "";
                while (linea != null) {
                    todo = todo + linea + "\n";
                    linea = br.readLine();
                }
                br.close();
                archivo.close();
                et2.setText(todo);
            } catch (IOException e) {
            }

La interfaz visual en tiempo de ejecución debe ser similar a esta:

Archivos de texto memoria interna

Este proyecto lo puede descargar en un zip desde este enlace: proyecto017.zip


Retornar