File con Android

In questo articolo svilupperemo una semplice app Android che usa i file interni al dispositivo.
Come esempio salviamo nome ed anno di nascita di una persona per ogni riga del file. Se volete già guardare l’effetto finale andate nella figura dell’app.
Verrà spiegato come:

  • creare un file di testo salvandolo nella memoria interna del proprio dispositivo
  • leggere un file carattere per carattere
  • leggere un file riga per riga
  • eliminare un file


Contenuti
Introduzione
Classi usate
Codice


Introduzione

L’ambiente di sviluppo usato è sempre Android Studio.
All’inizio della creazione dell’app scegliamo quella con Blank Activity ( chi non ha mai creato un’app può far riferimento all’articolo Calcolatrice Android ), in modo da aver già molto codice scritto in automatico.

Classi

La classi importanti usate per l’app sono:

FileOutputStream
per creare il file e scrivere successivamente in modalità APPEND
FileInputStream
per aprire il file e leggerlo
BufferedReader
per conservare in un Buffer (memoria d’appoggio) il contenuto del file letto con FileInputStream

Codice

Ecco quindi di seguito i sorgenti con alla fine di ognuno la spiegazione:
AndroidManifest.xml
activity_main.xml
strings.xml
dimens.xml
MainAcitvity.java


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="yasb.sondaggi" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Bè, il contenuto di AndroidManifest.xml è quello creato in automatico scegliendo la Blank activity all’inizio ed il significato è stato spiegato nell’esempio della Calcolatrice.

activity_main.xml

<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" tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView android:text="@string/titleMain" android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/txttitlesize"
    />
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="@dimen/PadNextTitle"
        >
        <TextView android:text="@string/txtnome" android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/txtsize"
            android:textStyle="bold"
            />
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/edtnome"
            android:textSize="@dimen/txtsize"
            android:id="@+id/edtNome"
            />
    </LinearLayout>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="@dimen/PadNextWIdget"
        >
    <TextView android:text="@string/txtanno" android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/txtsize"
        android:textStyle="bold"
        />
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/edtanno"
        android:textSize="@dimen/txtsize"
        android:id="@+id/edtAnno"
        />
    </LinearLayout>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/btnSalva"
        android:onClick="SalvaSondaggio"
        android:layout_marginTop="@dimen/PadNextFrame"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="leggi tutto il file"
        android:onClick="LeggiFile"
        android:layout_marginTop="@dimen/PadNextWIdget"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="leggi riga"
        android:onClick="LeggiFilePerRiga"
        android:layout_marginTop="@dimen/PadNextWIdget"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/btnReset"
        android:onClick="Reset"
        android:layout_marginTop="@dimen/PadNextWIdget"
        />

</LinearLayout>

L’activity appena scritta dovrebbe comparire come in figura:


FIle con Android

^
  • il pulsante “Salva”: chiama la funzione SalvaSondaggio che (crea il file se non esiste e poi) salva il “Nome” inserito e l'”anno di nascita” scrivendoli nel formato: “Nome: anno\n” e cioè andando accapo alla fine di ogni coppia “nome: anno” (vedi funzione SalvaSondaggio su: MainActivity.java dalla riga 79)
  • il pulsante “leggi tutto il file” chiama la funzione LeggiFile che legge carattere per carattere
  • il pulsante “leggi riga” legge una riga alla volta fino alla fine; segnala anche se il file è vuoto (o non è stato creato) e la fine del file dopo aver letto tutto le righe
  • il pulsante “Svuota File” chiama la funzione Reset che lo cancella

MainActivity.java

package yasb.sondaggi;

import android.content.Context;
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.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MainActivity extends ActionBarActivity {

    private EditText edtAnno;
    private EditText edtNome;
    private FileOutputStream outputStream;//File su cui scrivere
    private BufferedReader  lettore;//Buffer per leggere il file
    private InputStream flussoDiInput;//per conservare il flusso di input del file
    private String filename;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        filename = "sondaggi";
        edtAnno = (EditText)findViewById(R.id.edtAnno);
        edtNome = (EditText)findViewById(R.id.edtNome);
    }

    /* leggi File carattere per carattere*/
    public void LeggiFile(View v)
    {
        FileInputStream filedaleggere;
        try {

            filedaleggere = openFileInput(filename);
            InputStreamReader InputRead= new InputStreamReader(filedaleggere);

            char[] inputBuffer= new char[20];
            String s="";//stringa daleggere
            int charRead;
            while ((charRead=InputRead.read(inputBuffer))>0) {
            // char to string conversion
                String readstring=String.copyValueOf(inputBuffer,0,charRead);
                s +=readstring;
            }
            if(s.isEmpty())
                Toast.makeText(getBaseContext(), "File Vuoto!!!", Toast.LENGTH_SHORT).show();
            else
                Toast.makeText(getBaseContext(), s, Toast.LENGTH_SHORT).show();
            InputRead.close();
        }catch (Exception e){
            Toast.makeText(getBaseContext(), "File Vuoto!!!", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    public void SalvaSondaggio(View v)
    {
        String string1 = edtAnno.getText().toString();
        String strSeparatore = ": ";
        String string2 = edtNome.getText().toString();
        String strDaSalvare = string1 + strSeparatore + string2;
        String accapo = "\n";

        try {
            /* il MODE_APPEND serve sia per inserire alla fine di un 
             * file già esistente, sia per crearlo se non esiste
             */
            outputStream = openFileOutput(filename, Context.MODE_APPEND);
            outputStream.write(strDaSalvare.getBytes());
            outputStream.write(accapo.getBytes());//per andare accapo
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        edtAnno.setText("");//svuota la casella Anno
        edtNome.setText("");//svuota la casella Nome
        Toast.makeText(getBaseContext(), "Salvato !!! Grazie ;)", Toast.LENGTH_SHORT).show();
    }

    public void LeggiFilePerRiga(View v)
    {
        String linea;

        try {

            flussoDiInput = new FileInputStream(getApplicationContext().getFilesDir().toString()+"/"+filename);
            //flussoDiInput = this.getAssets().open(inStream);

            if(lettore == null)
                lettore = new BufferedReader(new InputStreamReader(flussoDiInput));

            linea = lettore.readLine();
            if (linea != null) {
                Toast.makeText(getBaseContext(), linea, Toast.LENGTH_SHORT).show();
            } else {
            //chiudi il file
                Toast.makeText(getBaseContext(), "Fine File!!!", Toast.LENGTH_SHORT).show();
                 flussoDiInput.close();
            }

        }catch (Exception e){
            Toast.makeText(getBaseContext(), "File Vuoto!!!", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    public void Reset(View v)
    {
        try {
            deleteFile(filename);
            lettore.reset();
            Toast.makeText(getBaseContext(), "File Svuotato!!!", Toast.LENGTH_SHORT).show();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

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

strings.xml

<resources>
    <string name="app_name">Sondaggi</string>
    <string name="action_settings">Impostazioni</string>
    <string name="titleMain">Sondaggio</string>
    <string name="txtanno">"Anno di nascita:"</string>
    <string name="edtanno">"digita anno"</string>
    <string name="txtnome">"Nome:"</string>
    <string name="edtnome">"digita nome"</string>
    <string name="btnSalva">"Salva"</string>
    <string name="btnReset">"Svuota File"</string>
</resources>

dimens.xml

<resources>
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="txttitlesize">32dip</dimen>
    <dimen name="txtsize">22dip</dimen>PadNextTitle
    <dimen name="PadNextTitle">32dip</dimen>
    <dimen name="PadNextWIdget">20dip</dimen>
    <dimen name="PadNextFrame">38dip</dimen>
</resources>