Lire / écrire une chaîne depuis / vers un fichier dans Android

213

Je souhaite enregistrer un fichier dans la mémoire de stockage interne en obtenant le texte saisi depuis EditText. Ensuite, je veux que le même fichier renvoie le texte entré sous forme de chaîne et l'enregistre dans une autre chaîne qui sera utilisée plus tard.

Voici le code:

package com.omm.easybalancerecharge;


import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

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

        final EditText num = (EditText) findViewById(R.id.sNum);
        Button ch = (Button) findViewById(R.id.rButton);
        TelephonyManager operator = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        String opname = operator.getNetworkOperatorName();
        TextView status = (TextView) findViewById(R.id.setStatus);
        final EditText ID = (EditText) findViewById(R.id.IQID);
        Button save = (Button) findViewById(R.id.sButton);

        final String myID = ""; //When Reading The File Back, I Need To Store It In This String For Later Use

        save.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                //Get Text From EditText "ID" And Save It To Internal Memory
            }
        });
        if (opname.contentEquals("zain SA")) {
            status.setText("Your Network Is: " + opname);
        } else {
            status.setText("No Network");
        }
        ch.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                //Read From The Saved File Here And Append It To String "myID"


                String hash = Uri.encode("#");
                Intent intent = new Intent(Intent.ACTION_CALL);
                intent.setData(Uri.parse("tel:*141*" + /*Use The String With Data Retrieved Here*/ num.getText()
                        + hash));
                startActivity(intent);
            }
        });
    }

J'ai inclus des commentaires pour vous aider à analyser plus en détail mes points quant à l'endroit où je veux que les opérations soient effectuées / les variables à utiliser.

Major Aly
la source
2
la question est "comment lire / écrire dans / depuis un fichier?"
Dmitri Gudkov
Avez-vous envisagé d'utiliser les préférences de l'application pour stocker vos chaînes?
sdabet
4
BTW, assurez-vous de mettre la permission sur le fichier mainfest, pour fonctionner avec le stockage ...
Dmitri Gudkov
Ceci est mon application à moitié complète avec de nombreux changements à mettre en œuvre. Mon idée est que l'utilisateur n'entre l'ID qu'une seule fois lors de la première exécution de l'application. Ensuite, l'application référencera cet ID stocké autant de fois que l'utilisateur exécutera l'application. Les autorisations sont toutes ajoutées au manifeste.
Major Aly

Réponses:

335

J'espère que cela pourrait vous être utile.

Écrire un fichier:

private void writeToFile(String data,Context context) {
    try {
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("config.txt", Context.MODE_PRIVATE));
        outputStreamWriter.write(data);
        outputStreamWriter.close();
    }
    catch (IOException e) {
        Log.e("Exception", "File write failed: " + e.toString());
    } 
}

Lire le fichier:

private String readFromFile(Context context) {

    String ret = "";

    try {
        InputStream inputStream = context.openFileInput("config.txt");

        if ( inputStream != null ) {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String receiveString = "";
            StringBuilder stringBuilder = new StringBuilder();

            while ( (receiveString = bufferedReader.readLine()) != null ) {
                stringBuilder.append("\n").append(receiveString);
            }

            inputStream.close();
            ret = stringBuilder.toString();
        }
    }
    catch (FileNotFoundException e) {
        Log.e("login activity", "File not found: " + e.toString());
    } catch (IOException e) {
        Log.e("login activity", "Can not read file: " + e.toString());
    }

    return ret;
}
R9J
la source
43
Si la classe n'est pas étendue à partir de Activity, l'utilisation de la méthode "openFileInput ()" devrait être comme ceci: context.openFileInput ()
Behzad
11
Remarque: Le code ci-dessus fonctionne bien, mais la chaîne résultante ne contiendra aucun des sauts de ligne du fichier. Pour ajouter à nouveau des sauts de ligne, modifiez la ligne "stringBuilder.append (receiveString);" à "stringBuilder.append (receiveString) .append (" \ n ");". Si vous vous attendez à d'autres caractères de saut de ligne (par exemple, les fichiers texte Windows auront \ r etc.), dans votre chaîne finale, vous devrez l'adapter un peu plus.
treesAreEverywhere
27
où ce fichier de configuration enregistre dans un appareil réel? je n'ai pas pu le trouver pour vérifier :(
Mahdi
4
Je pense que la fermeture des flux devrait être dans le finalbloc comme dans la réponse @SharkAlley
Yurii K
4
@Kenji, le fichier est enregistré dans le répertoire de fichiers de l'application (par exemple / data / data / <package_name> /files/config.txt). Le processus de l'application peut y accéder, mais pas tous les processus du système d'exploitation. La mise en œuvre peut différer selon la version Android exécutée par votre appareil. Vous pouvez vérifier la mise en œuvre de l'AOSP en ligne. Par exemple, pour Android 8.1_r5: android.googlesource.com/platform/frameworks/base/+/…
vhamon
189

Pour ceux qui recherchent une stratégie générale pour lire et écrire une chaîne dans un fichier:

Tout d'abord, obtenez un objet fichier

Vous aurez besoin du chemin de stockage. Pour le stockage interne, utilisez:

File path = context.getFilesDir();

Pour le stockage externe (carte SD), utilisez:

File path = context.getExternalFilesDir(null);

Créez ensuite votre objet fichier:

File file = new File(path, "my-file-name.txt");

Écrivez une chaîne dans le fichier

FileOutputStream stream = new FileOutputStream(file);
try {
    stream.write("text-to-write".getBytes());
} finally {
    stream.close();
}

Ou avec Google Guava

Contenu de la chaîne = Files.toString (fichier, StandardCharsets.UTF_8);

Lire le fichier dans une chaîne

int length = (int) file.length();

byte[] bytes = new byte[length];

FileInputStream in = new FileInputStream(file);
try {
    in.read(bytes);
} finally {
    in.close();
}

String contents = new String(bytes);   

Ou si vous utilisez Google Guava

String contents = Files.toString(file,"UTF-8");

Pour être complet, je mentionnerai

String contents = new Scanner(file).useDelimiter("\\A").next();

qui ne nécessite aucune bibliothèque, mais des benchmarks 50% - 400% plus lents que les autres options (dans divers tests sur mon Nexus 5).

Remarques

Pour chacune de ces stratégies, il vous sera demandé d'attraper une exception IOException.

L'encodage de caractères par défaut sur Android est UTF-8.

Si vous utilisez un stockage externe, vous devrez ajouter à votre manifeste:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

ou

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

L'autorisation d'écriture implique une autorisation de lecture, vous n'avez donc pas besoin des deux.

SharkAlley
la source
Ok, par exemple, je veux qu'un utilisateur voit tous ses messages, et quand il va sur un autre écran et revient, dois-je le dessiner à nouveau ou parce qu'il est mis en cache, il le sort simplement du cache et l'affiche, s'il le fait ne fait que le retirer, comment ajouter un si conditionnel pour dire de ne pas interroger mes serveurs
Lion789
4
Ne fais pas ça comme new File(path + "/my-file-name.txt");. Cela défie une grande partie du sens de File. Utilisez new File(path, "my-file-name.txt");plutôt.
JimmyB
@HannoBinder Android fonctionne toujours sur Linux, donc le séparateur est garanti "/". Quel serait l'avantage d'utiliser un nouveau fichier (chemin d'accès, "mon-nom-de-fichier.txt") dans ce contexte? (Je suis heureux de mettre à jour la réponse s'il y a une raison de le faire.)
SharkAlley
1
Fileest là pour une raison. Dans votre cas, vous pouvez tout aussi bien sauter Fileet faire new FileInputStream(path + "/my-file-name.txt");ce que je ne recommande pas. (Et si pathcontient un tirage /par exemple?)
JimmyB
Modifié selon votre suggestion. Merci :)
SharkAlley
37
public static void writeStringAsFile(final String fileContents, String fileName) {
    Context context = App.instance.getApplicationContext();
    try {
        FileWriter out = new FileWriter(new File(context.getFilesDir(), fileName));
        out.write(fileContents);
        out.close();
    } catch (IOException e) {
        Logger.logError(TAG, e);
    }
}

public static String readFileAsString(String fileName) {
    Context context = App.instance.getApplicationContext();
    StringBuilder stringBuilder = new StringBuilder();
    String line;
    BufferedReader in = null;

    try {
        in = new BufferedReader(new FileReader(new File(context.getFilesDir(), fileName)));
        while ((line = in.readLine()) != null) stringBuilder.append(line);

    } catch (FileNotFoundException e) {
        Logger.logError(TAG, e);
    } catch (IOException e) {
        Logger.logError(TAG, e);
    } 

    return stringBuilder.toString();
}
Eugène
la source
7
App!? qu'est-ce que c'est censé être!?
alap
@alap est quelque chose que @Eugene utilise pour récupérer statiquement le contexte de l'application. Il en a besoin context.getFilesDir(). Vous pouvez simplement remplacer les occurrences de new File(context.getFilesDir(), fileName)par un Fileobjet ou une Stringfonction passée à la place de fileName.
lorenzo-s
7

Juste quelques modifications sur la lecture de la chaîne à partir d'une méthode de fichier pour plus de performances

private String readFromFile(Context context, String fileName) {
    if (context == null) {
        return null;
    }

    String ret = "";

    try {
        InputStream inputStream = context.openFileInput(fileName);

        if ( inputStream != null ) {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);               

            int size = inputStream.available();
            char[] buffer = new char[size];

            inputStreamReader.read(buffer);

            inputStream.close();
            ret = new String(buffer);
        }
    }catch (Exception e) {
        e.printStackTrace();
    }

    return ret;
}
Tai Le Anh
la source
6

vérifiez le code ci-dessous.

Lecture à partir d'un fichier dans le système de fichiers.

FileInputStream fis = null;
    try {

        fis = context.openFileInput(fileName);
        InputStreamReader isr = new InputStreamReader(fis);
        // READ STRING OF UNKNOWN LENGTH
        StringBuilder sb = new StringBuilder();
        char[] inputBuffer = new char[2048];
        int l;
        // FILL BUFFER WITH DATA
        while ((l = isr.read(inputBuffer)) != -1) {
            sb.append(inputBuffer, 0, l);
        }
        // CONVERT BYTES TO STRING
        String readString = sb.toString();
        fis.close();

    catch (Exception e) {

    } finally {
        if (fis != null) {
            fis = null;
        }
    }

le code ci-dessous consiste à écrire le fichier dans le système de fichiers interne.

FileOutputStream fos = null;
    try {

        fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        fos.write(stringdatatobestoredinfile.getBytes());
        fos.flush();
        fos.close();

    } catch (Exception e) {

    } finally {
        if (fos != null) {
            fos = null;
        }
    }

Je crois que ceci vous aidera.

Raj
la source
3

Je suis un peu débutant et j'ai eu du mal à faire fonctionner ça aujourd'hui.

Ci-dessous est la classe avec laquelle je me suis retrouvé. Cela fonctionne, mais je me demandais à quel point ma solution était imparfaite. Quoi qu'il en soit, j'espérais que certains d'entre vous, des gens plus expérimentés, seraient prêts à jeter un œil à ma classe IO et à me donner quelques conseils. À votre santé!

public class HighScore {
    File data = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator);
    File file = new File(data, "highscore.txt");
    private int highScore = 0;

    public int readHighScore() {
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            try {
                highScore = Integer.parseInt(br.readLine());
                br.close();
            } catch (NumberFormatException | IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            try {
                file.createNewFile();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
            e.printStackTrace();
        }
        return highScore;
    }

    public void writeHighScore(int highestScore) {
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter(file));
            bw.write(String.valueOf(highestScore));
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Nihilarien
la source
Vous n'avez pas besoin de créer un nouveau fichier s'il n'y en a pas.
rml
1

la première chose dont nous avons besoin est les autorisations dans AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />

donc dans une classe asyncTask Kotlin, nous traitons la création du fichier

    import android.os.AsyncTask
    import android.os.Environment
    import android.util.Log
    import java.io.*
    class WriteFile: AsyncTask<String, Int, String>() {
        private val mFolder = "/MainFolder"
        lateinit var folder: File
        internal var writeThis = "string to cacheApp.txt"
        internal var cacheApptxt = "cacheApp.txt"
        override fun doInBackground(vararg writethis: String): String? {
            val received = writethis[0]
            if(received.isNotEmpty()){
                writeThis = received
            }
            folder = File(Environment.getExternalStorageDirectory(),"$mFolder/")
            if(!folder.exists()){
                folder.mkdir()
                val readME = File(folder, cacheApptxt)
                val file = File(readME.path)
                val out: BufferedWriter
                try {
                    out = BufferedWriter(FileWriter(file, true), 1024)
                    out.write(writeThis)
                    out.newLine()
                    out.close()
                    Log.d("Output_Success", folder.path)
                } catch (e: Exception) {
                    Log.d("Output_Exception", "$e")
                }
            }
            return folder.path

    }

        override fun onPostExecute(result: String) {
            super.onPostExecute(result)

            if(result.isNotEmpty()){
                //implement an interface or do something
                Log.d("onPostExecuteSuccess", result)
            }else{
                Log.d("onPostExecuteFailure", result)
            }
        }

    }

Bien sûr, si vous utilisez Android au-dessus d'Api 23, vous devez gérer la demande pour autoriser l'écriture dans la mémoire de l'appareil. Quelque chose comme ça

    import android.Manifest
    import android.content.Context
    import android.content.pm.PackageManager
    import android.os.Build
    import androidx.appcompat.app.AppCompatActivity
    import androidx.core.app.ActivityCompat
    import androidx.core.content.ContextCompat

    class ReadandWrite {
        private val mREAD = 9
        private val mWRITE = 10
        private var readAndWrite: Boolean = false
        fun readAndwriteStorage(ctx: Context, atividade: AppCompatActivity): Boolean {
            if (Build.VERSION.SDK_INT < 23) {
                readAndWrite = true
            } else {
                val mRead = ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_EXTERNAL_STORAGE)
                val mWrite = ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE)

                if (mRead != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(atividade, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), mREAD)
                } else {
                    readAndWrite = true
                }

                if (mWrite != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(atividade, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), mWRITE)
                } else {
                    readAndWrite = true
                }
            }
            return readAndWrite
        }
    }

puis dans une activité, exécutez l'appel.

  var pathToFileCreated = ""
    val anRW = ReadandWrite().readAndwriteStorage(this,this)
    if(anRW){
        pathToFileCreated =  WriteFile().execute("onTaskComplete").get()
        Log.d("pathToFileCreated",pathToFileCreated)
    }
AllanRibas
la source
ces autorisations de stockage interne ne sont pas valides.
Lerk
0

Kotlin

class FileReadWriteService {

    private var context:Context? = ContextHolder.instance.appContext

    fun writeFileOnInternalStorage(fileKey: String, sBody: String) {
        val file = File(context?.filesDir, "files")
        try {
            if (!file.exists()) {
                file.mkdir()
            }
            val fileToWrite = File(file, fileKey)
            val writer = FileWriter(fileToWrite)
            writer.append(sBody)
            writer.flush()
            writer.close()
        } catch (e: Exception) {
            Logger.e(classTag, e)
        }
    }

    fun readFileOnInternalStorage(fileKey: String): String {
        val file = File(context?.filesDir, "files")
        var ret = ""
        try {
            if (!file.exists()) {
                return ret
            }
            val fileToRead = File(file, fileKey)
            val reader = FileReader(fileToRead)
            ret = reader.readText()
            reader.close()
        } catch (e: Exception) {
            Logger.e(classTag, e)
        }
        return ret
    }
}
Sazzad Hissain Khan
la source