Stockage interne
Lorsque vous devez travailler avec des types plus complexes tels que audio, vidéo ou images, vous pouvez utiliser le stockage interne (mémoire interne du périphérique) ou externe (mémoire accessible au public, par exemple, SDCARD). Un stockage externe peut Être accessible par l'application qui l'a créée, par d'autres applications et même par l'utilisateurn survivre à l'application, même après sa désinstallation Un stockage interneEst accessible uniquement par l'application qui l'a créé; aucune autre application ne peut y accéderSera supprimé lors de la désinstallation de l'application Dans ce chapitre, nous ne travaillerons qu'avec le stockage interne.
Comment travailler avec le stockage interne
Pour enregistrer des données sur un stockage interne, nous devons d’abord créer un objet FileInputStream; cela peut être géré par la méthode openFileInput de la classe Activity. Lorsqu'un fichier est ouvert en écriture, tout son contenu précédent est supprimé. Il est toutefois possible d'ouvrir un fichier de manière à pouvoir ajouter un nouveau contenu, en préservant ainsi le contenu précédent.
FileOutputStream fout = openFileOutput(<name of file>, Context.MODE_APPEND);
Si vous ne voulez pas ouvrir le fichier en mode ajout, passez simplement Context.MODE_PRIVATE comme second paramètre. Une fois le fichier préparé, nous pouvons lui écrire des données. fout.write (<données de chaîne>); Les méthodes openFileOutput et write peuvent toutes deux générer des exceptions. Elles doivent donc être gérées en renvoyant l'exception ou en la utilisant à l'aide d'une construction try-catch. Dans notre exemple, nous avons utilisé les blocs try-catch pour gérer les exceptions possibles. La lecture de données depuis une mémoire interne est également simple. Cela ressemble beaucoup au processus d’écriture de données; nous devons simplement préparer un FileInputStream puis le lire.
FileInputStream fin = openFileInput(<name of file>);
The file input is a stream. The basic idea is to read bytes from it a chunk at a time until we reach the end of the file.
Let’s explore the details in a demo project.
Demonstration du Projet
Nous montrerons comment développer l’application de stockage interne comme indiqué dans le tableau 10-4.
Table 10-4. Project details for InternalStorage
Application name
|
InternalStorage
|
Project location
|
Use the default
|
Form factor
|
Phone and tablet only
|
Minimum SDK
|
API 23 Marshmallow
|
Type of activity
|
Empty
|
Activity name
|
MainActivity (default)
|
Layout name
|
activity_main (default)
|
Les détails relatifs à la configuration du fichier de présentation unique (activity_main) sont illustrés à la Figure 10-13 et au Listing 10-12.
Figure 10-13. activity_main
Le fichier de présentation est typique de notre projet de démonstration habituel, mais il convient de souligner les points suivants. 1. Le EditText étant censé capturer plusieurs lignes de texte, vous devez donc définir son attribut «inputType» sur «textMultiline». Vous pouvez le faire dans la fenêtre de l'inspecteur d'attributs en mode conception, ou bien écrire directement dans le fichier XML, comme indiqué dans le Listing 10-12.2. Nous n'allons pas gérer les événements de clic par programmation, nous avons donc défini les valeurs pour les attributs «onClick» des deux boutons.
Listing 10-12. activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.ted.internalstorage.MainActivity">
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.ted.internalstorage.MainActivity">
Data Persistence
<EditText
android:id="@+id/edittext"
android:layout_width="359dp"
android:layout_height="193dp"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:ems="10"
android:inputType="textMultiLine"
//This makes it multiline
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/btnsave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:layout_marginTop="11dp"
android:onClick="saveData"
android:text="Save"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edittext"/>
<Button
android:id="@+id/btnload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="21dp"
android:layout_marginTop="11dp"
android:onClick="loadData"
android:text="Load"
app:layout_constraintStart_toEndOf="@+id/btnsave"
app:layout_constraintTop_toBottomOf="@+id/edittext"/>
<TextView
android:id="@+id/textview"
android:layout_width="360dp"
android:layout_height="0dp"
android:layout_marginBottom="9dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="14dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnsave"/> </android.support.constraint.ConstraintLayout>
<EditText
android:id="@+id/edittext"
android:layout_width="359dp"
android:layout_height="193dp"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:ems="10"
android:inputType="textMultiLine"
//This makes it multiline
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/btnsave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="24dp"
android:layout_marginTop="11dp"
android:onClick="saveData"
android:text="Save"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edittext"/>
<Button
android:id="@+id/btnload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="21dp"
android:layout_marginTop="11dp"
android:onClick="loadData"
android:text="Load"
app:layout_constraintStart_toEndOf="@+id/btnsave"
app:layout_constraintTop_toBottomOf="@+id/edittext"/>
<TextView
android:id="@+id/textview"
android:layout_width="360dp"
android:layout_height="0dp"
android:layout_marginBottom="9dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="14dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnsave"/> </android.support.constraint.ConstraintLayout>
Le Listing 10-13 montre la structure de MainActivity. La méthode saveData est associée au bouton “SAVE” et loadData est associée au bouton “LOAD”.
Listing 10-13. Overview of MainActivity
public class MainActivity extends AppCompatActivity { EditText editText;
private String filename
= "myfile.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.edittext);
}
public void saveData
(View v
) { ...
}
public void loadData
(View v
) { ...
}
}
public class MainActivity extends AppCompatActivity { EditText editText;
private String filename = "myfile.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.edittext);
}
public void saveData(View v) { ... }
public void loadData(View v) { ... }
}
ditText est défini en tant que variable membre car nous devrons y faire référence à partir de saveData et de loadData.Le nom de fichier est défini en tant que variable membre pour la même raison que dans no. 1
Listing 10-14. Code for saveData
public void saveData
(View v
) {
String str
= editText.
getText().
toString();
try {
out
= openFileOutput
(filename,
Context.
MODE_APPEND);
out.write(str.getBytes());
e.printStackTrace();
// You should do more logging here
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
e.printStackTrace();
}
}
}
}
public void saveData(View v) {
String str = editText.getText().toString();
FileOutputStream out = null;
try {
out = openFileOutput(filename, Context.MODE_APPEND);
out.write(str.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
// You should do more logging here
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
openFileOutput prépare un fichier pour l'écriture. Le premier argument est le nom du fichier à créer et le second argument détermine si nous pouvons ajouter au fichier ou s'il sera écrasé à chaque ouverture du fichier. Dans ce cas, nous avons choisi le mode Ajout afin de pouvoir conserver le contenu original du fichier. Cette méthode peut générer une «FileNotFoundException»; c’est pourquoi il doit être entouré d’un bloc try-catchEffectue l'écriture réelle des données sur le disque. Cela ne peut fonctionner qu'avec des octets, cependant; c’est pourquoi nous avions besoin de la méthode getBytes. Cette méthode peut générer une “IOException”; c’est pourquoi nous avons dû préciser cela dans la clause de captureNous devons savoir que l'objet FileOutputStream n'est pas null avant de poursuivre. Cela ferme le fichier et libère les ressources système qui lui sont associées. Cette méthode peut générer une «IOException», d’où la nécessité d’une construction imbriquée try-catch
Listing 10-15. Code for loadData
public void loadData
(View v
) {
TextView tv = (TextView) findViewById(R.id.textview);
StringBuilder sb = new StringBuilder();
try {
in = openFileInput(filename);
int read = 0;
while((read = in.read()) != -1) {
sb.append((char) read);
}
tv.setText(sb.toString());
e.printStackTrace();
e.printStackTrace();
}
finally {
if (in != null) {
try {
in.close();
e.printStackTrace();
}
}
}
}
public void loadData(View v) {
TextView tv = (TextView) findViewById(R.id.textview);
FileInputStream in = null;
StringBuilder sb = new StringBuilder();
try {
in = openFileInput(filename);
int read = 0;
while((read = in.read()) != -1) {
sb.append((char) read);
}
tv.setText(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Préparez le fichier pour le lire. Cette méthode peut générer une «FileNotFoundException»; c'est pourquoi il doit être entouré d'un bloc try-catch, comme openFileOuput. La méthode de lecture du flux d'entrée lit un octet de données à la fois, et lorsqu'elle atteint la fin du fichier où il n'y a plus rien à lire, elle retour -1La méthode in.read () renvoie un int; nous devons le convertir en caractère afin que nous puissions utiliser StringBuilderLorsque nous arrivons à la fin du fichier, nous pouvons convertir l'objet StringBuilder en String et le définir comme texte pour la vue Texte.Vous pouvez inspecter le contenu du ou des fichiers de stockage interne en utilisant Android Device Monitor. Le fichier se trouve dans les données - données <package de projet + nom>.