Leer / escribir cadena de / a un archivo en Android

213

Quiero guardar un archivo en el almacenamiento interno obteniendo el texto ingresado desde EditText. Luego, quiero que el mismo archivo devuelva el texto ingresado en forma de Cadena y lo guarde en otra Cadena que se utilizará más adelante.

Aquí está el código:

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

He incluido comentarios para ayudarlo a analizar mis puntos en cuanto a dónde quiero que se realicen las operaciones / variables.

Mayor aly
fuente
2
la pregunta es "¿cómo leer / escribir en / desde un archivo?"
Dmitri Gudkov
¿Consideró usar las preferencias de la aplicación para almacenar sus cadenas?
sdabet
44
Por cierto, asegúrese de poner permiso al archivo mainfest, para operar con almacenamiento ...
Dmitri Gudkov
Esta es mi aplicación medio completa con muchos cambios para implementar. Mi idea es que el usuario ingrese la ID solo una vez en la primera ejecución de la aplicación. Luego, la aplicación hará referencia a esa ID almacenada tantas veces como el usuario ejecute la aplicación. Todos los permisos se agregan al manifiesto.
Mayor Aly

Respuestas:

335

Espero que esto te sea útil.

Escribir archivo:

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

Leer archivo:

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
fuente
43
Si la clase no se extiende desde Activity, el uso del método "openFileInput ()" debería ser así: context.openFileInput ()
Behzad
11
Nota: El código anterior funciona bien, pero la Cadena resultante no contendrá ninguno de los saltos de línea del archivo. Para agregar saltos de línea nuevamente, cambie la línea "stringBuilder.append (recibirString); a "stringBuilder.append (recibirString) .append (" \ n ");". Si espera otros caracteres de salto de línea (por ejemplo, los archivos de texto de Windows tendrán \ r, etc.), en su cadena final, tendrá que adaptar esto un poco más.
treesAreEverywhere
27
donde este archivo de configuración se guarda en un dispositivo real? no pude encontrarlo para comprobar :(
Mahdi
44
Creo que cerrar las transmisiones debería estar en el finalbloque como en la respuesta de @SharkAlley
Yurii K
44
@Kenji, el archivo se guarda en el directorio de archivos de la aplicación (es decir, / data / data / <package_name> /files/config.txt). El proceso de la aplicación puede acceder a él, pero no todos los procesos del sistema operativo. La implementación puede variar según la versión de Android que ejecute su dispositivo. Puede verificar la implementación del AOSP en línea. Por ejemplo, para Android 8.1_r5: android.googlesource.com/platform/frameworks/base/+/…
vhamon
189

Para aquellos que buscan una estrategia general para leer y escribir una cadena para archivar:

Primero, obtenga un objeto de archivo

Necesitarás la ruta de almacenamiento. Para el almacenamiento interno, use:

File path = context.getFilesDir();

Para el almacenamiento externo (tarjeta SD), use:

File path = context.getExternalFilesDir(null);

Luego cree su objeto de archivo:

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

Escribe una cadena en el archivo

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

O con Google Guava

Contenido de la cadena = Files.toString (archivo, StandardCharsets.UTF_8);

Leer el archivo a una cadena

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 si estás usando Google Guava

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

Para completar, mencionaré

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

que no requiere bibliotecas, pero los puntos de referencia son 50% - 400% más lentos que las otras opciones (en varias pruebas en mi Nexus 5).

Notas

Para cada una de estas estrategias, se le pedirá que capture una IOException.

La codificación de caracteres predeterminada en Android es UTF-8.

Si está utilizando almacenamiento externo, deberá agregar a su manifiesto:

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

o

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

El permiso de escritura implica permiso de lectura, por lo que no necesita ambos.

TiburónAlley
fuente
Ok, por ejemplo, quiero que un usuario vea todas sus publicaciones, y cuando vaya a otra pantalla y regrese, ¿necesito dibujarlo nuevamente o porque está en caché, solo lo saca del caché y solo lo muestra, si es simplemente lo saca, ¿cómo agrego un if condicional para decir que no consulte mis servidores?
Lion789
44
No lo hagas así new File(path + "/my-file-name.txt");. Esto desafía gran parte del sentido de File. Usar en su new File(path, "my-file-name.txt");lugar.
JimmyB
@HannoBinder Android siempre se ejecuta sobre Linux, por lo que se garantiza que el separador sea "/". ¿Cuál sería el beneficio de usar un nuevo archivo (ruta, "my-file-name.txt") en este contexto? (Me complace actualizar la respuesta si hay una razón para hacerlo)
SharkAlley
1
FileEstá ahí por una razón. En su caso, podría omitir Filey simplemente hacer new FileInputStream(path + "/my-file-name.txt");, lo que no recomiendo. (¿Qué pasa si pathcontiene un final, /por ejemplo?)
JimmyB
Editado por su sugerencia. Gracias :)
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();
}
Eugene
fuente
77
App!? ¿Qué se supone que es?
alap
@alap Es algo que @Eugene está usando para recuperar el contexto de la aplicación de forma estática. Lo necesita para context.getFilesDir(). Simplemente puede reemplazar las ocurrencias de new File(context.getFilesDir(), fileName)con un Fileobjeto o una Stringfunción pasada a en lugar de fileName.
lorenzo-s
7

Solo algunas modificaciones en la lectura de cadenas de un método de archivo para obtener más rendimiento

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
fuente
6

verifique el siguiente código.

Lectura de un archivo en el sistema de archivos.

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

El siguiente código es escribir el archivo en el sistema de archivos 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;
        }
    }

Creo que esto te ayudará.

Raj
fuente
3

Soy un poco principiante y luché para que esto funcione hoy.

A continuación se muestra la clase con la que terminé. Funciona, pero me preguntaba qué tan imperfecta es mi solución. De todos modos, esperaba que algunos de ustedes, personas con más experiencia, estén dispuestos a echar un vistazo a mi clase de IO y darme algunos consejos. ¡Salud!

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();
        }
    }
}
Nihilarian
fuente
No necesita crear un nuevo archivo si no hay ningún archivo allí.
rml
1

lo primero que necesitamos son los permisos en 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" />

así que en una clase asyncTask Kotlin, tratamos la creación del archivo

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

    }

Por supuesto, si está utilizando Android por encima de Api 23, debe manejar la solicitud para permitir la escritura en la memoria del dispositivo. Algo como esto

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

luego, en una actividad, ejecute la llamada.

  var pathToFileCreated = ""
    val anRW = ReadandWrite().readAndwriteStorage(this,this)
    if(anRW){
        pathToFileCreated =  WriteFile().execute("onTaskComplete").get()
        Log.d("pathToFileCreated",pathToFileCreated)
    }
AllanRibas
fuente
esos permisos de almacenamiento interno no son válidos.
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
fuente