Lettura / scrittura di stringhe da / a un file in Android


213

Voglio salvare un file nella memoria interna ottenendo il testo immesso da EditText. Quindi voglio che lo stesso file restituisca il testo immesso in forma di stringa e lo salvi in ​​un'altra stringa che verrà utilizzata in seguito.

Ecco il codice:

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

Ho incluso commenti per aiutarti ad analizzare ulteriormente i miei punti su dove voglio che le operazioni vengano eseguite / le variabili vengano utilizzate.


2
la domanda è "come leggere / scrivere nel / dal file?"
Dmitri Gudkov,

Hai preso in considerazione l'utilizzo delle preferenze dell'app per memorizzare le tue stringhe?
sabato

4
A proposito, assicurati di mettere l'autorizzazione per il file mainfest, per operare con l'archiviazione ...
Dmitri Gudkov,

Questa è la mia app mezza completa con molte modifiche da implementare. La mia idea è che l'utente inserisca l'ID una sola volta alla prima esecuzione dell'app. Quindi l'app farà riferimento a tale ID memorizzato tutte le volte che l'utente esegue l'app. Le autorizzazioni vengono tutte aggiunte al manifest.
Maggiore Aly

Risposte:


335

Spero che questo possa esserti utile.

Scrivi file:

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

Leggi il file:

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

43
Se la classe non viene estesa dall'attività, l'utilizzo del metodo "openFileInput ()" dovrebbe essere simile al seguente: context.openFileInput ()
Behzad,

11
Nota: il codice sopra funziona bene, ma la stringa risultante non conterrà alcuna interruzione di riga del file. Per aggiungere nuovamente interruzioni di riga, cambia la riga "stringBuilder.append (receiveString);" a "stringBuilder.append (receiveString) .append (" \ n ");". Se ti aspetti altri caratteri di interruzione di riga (ad es. I file di testo di Windows avranno \ r ecc.), Nella tua stringa finale, dovrai adattarlo un po 'di più.
treesAreEwherewhere

27
dove salva questo file di configurazione nel dispositivo reale? non sono riuscito a trovarlo per controllare :(
Mahdi

4
Penso che i flussi di chiusura dovrebbero essere nel finalblocco come nella risposta @SharkAlley
Yurii K

4
@Kenji il file viene salvato nella directory dei file dell'app (ad es. / Data / data / <nome_pacchetto> /files/config.txt). Il processo dell'app può accedervi ma non tutti i processi nel sistema operativo. L'implementazione potrebbe differire in base alla versione Android in esecuzione sul dispositivo. Puoi controllare l'implementazione dell'AOSP online. Ad esempio, per Android 8.1_r5: android.googlesource.com/platform/frameworks/base/+/…
vhamon

189

Per coloro che cercano una strategia generale per leggere e scrivere una stringa su file:

Innanzitutto, ottieni un oggetto file

Avrai bisogno del percorso di archiviazione. Per la memoria interna, utilizzare:

File path = context.getFilesDir();

Per la memoria esterna (scheda SD), utilizzare:

File path = context.getExternalFilesDir(null);

Quindi crea il tuo oggetto file:

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

Scrivi una stringa nel file

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

O con Google Guava

Contenuto della stringa = Files.toString (file, StandardCharsets.UTF_8);

Leggi il file su una stringa

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

O se stai usando Google Guava

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

Per completezza, citerò

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

che non richiede librerie, ma benchmark del 50% - 400% più lenti rispetto alle altre opzioni (in vari test sul mio Nexus 5).

Appunti

Per ciascuna di queste strategie, ti verrà chiesto di catturare un'eccezione IOException.

La codifica dei caratteri predefinita su Android è UTF-8.

Se stai utilizzando una memoria esterna, dovrai aggiungere al tuo manifest:

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

o

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

Il permesso di scrittura implica il permesso di lettura, quindi non hai bisogno di entrambi.


Ok, per esempio, voglio che un utente veda tutti i suoi post, e quando va in un'altra schermata e torna indietro, devo disegnarlo di nuovo o perché è memorizzato nella cache, lo estrae dalla cache e lo mostra, se basta estrarlo, come posso aggiungere un if condizionale per dire di non interrogare i miei server
Lion789

4
Non farlo come new File(path + "/my-file-name.txt");. Questo sfida gran parte del senso di File. Usa new File(path, "my-file-name.txt");invece.
JimmyB,

@HannoBinder Android funziona sempre su Linux, quindi il separatore è garantito "/". Quale sarebbe il vantaggio di utilizzare il nuovo file (percorso, "my-file-name.txt") in questo contesto? (Sono felice di aggiornare la risposta se c'è un motivo.)
SharkAlley,

1
Fileè lì per un motivo. Nel tuo caso, potresti anche saltare Filee fare new FileInputStream(path + "/my-file-name.txt");, cosa che non ti consiglio. (E se pathcontiene un trailing /per esempio?)
JimmyB,

Modificato su tuo suggerimento. Grazie :)
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();
}

7
App!? cosa dovrebbe essere!?
alap

@alap È qualcosa che @Eugene sta usando per recuperare staticamente il contesto dell'app. Ne ha bisogno per context.getFilesDir(). Puoi semplicemente sostituire le occorrenze di new File(context.getFilesDir(), fileName)con un Fileoggetto o una Stringfunzione passata anziché fileName.
lorenzo-s,

7

Solo alcune modifiche alla lettura della stringa da un metodo di file per maggiori prestazioni

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

6

controlla il codice qui sotto.

Lettura da un file nel filesystem.

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

sotto il codice è di scrivere il file nel filesystem interno.

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

Penso che questo ti aiuterà.


3

Sono un po 'alle prime armi e faccio fatica a farlo funzionare oggi.

Di seguito è la classe con cui sono finito. Funziona ma mi chiedevo quanto sia imperfetta la mia soluzione. Ad ogni modo, speravo che alcuni di voi più esperti potessero essere disposti a dare un'occhiata alla mia classe IO e darmi qualche consiglio. Saluti!

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

Non è necessario creare un nuovo file se non è presente alcun file.
rml,

1

la prima cosa di cui abbiamo bisogno sono le autorizzazioni in 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" />

quindi in una classe asyncTask Kotlin, trattiamo la creazione del file

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

    }

Ovviamente se si utilizza Android sopra Api 23, è necessario gestire la richiesta per consentire la scrittura nella memoria del dispositivo. Qualcosa come questo

    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
        }
    }

quindi in un'attività, esegui la chiamata.

  var pathToFileCreated = ""
    val anRW = ReadandWrite().readAndwriteStorage(this,this)
    if(anRW){
        pathToFileCreated =  WriteFile().execute("onTaskComplete").get()
        Log.d("pathToFileCreated",pathToFileCreated)
    }

tali permessi di archiviazione interna non sono validi.
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
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.