Ler / Gravar String de / para um Arquivo no Android

213

Quero salvar um arquivo no armazenamento interno, obtendo o texto inserido no EditText. Então, eu quero que o mesmo arquivo retorne o texto inserido no formulário String e salve-o em outra String que será usada posteriormente.

Aqui está o 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);
            }
        });
    }

Incluí comentários para ajudá-lo a analisar melhor meus pontos sobre onde eu quero que as operações sejam feitas / variáveis ​​sejam usadas.

Major Aly
fonte
2
a pergunta é "como ler / gravar para / do arquivo?"
Dmitri Gudkov
Você considerou usar as preferências do aplicativo para armazenar suas strings?
Sdabet
4
BTW, não se esqueça de colocar a permissão para o arquivo mainfest, para operar com armazenamento ...
Dmitri Gudkov
Este é o meu aplicativo meio completo, com muitas alterações para implementar. Minha ideia é que o usuário insira o ID apenas uma vez na primeira execução do aplicativo. Em seguida, o aplicativo fará referência ao ID armazenado quantas vezes o usuário executar o aplicativo. Todas as permissões são adicionadas ao manifesto.
Major Aly

Respostas:

334

Espero que isso possa ser útil para você.

Gravar arquivo:

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

Ler arquivo:

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
fonte
43
Se a classe não for estendida de Activity, o uso do método "openFileInput ()" deve ser assim: context.openFileInput ()
Behzad
11
Nota: O código acima funciona bem, mas a String resultante não conterá nenhuma das quebras de linha do arquivo. Para adicionar quebras de linha novamente, altere a linha "stringBuilder.append (receiveString);" para "stringBuilder.append (receiveString) .append (" \ n ");". Se você espera outros caracteres de quebra de linha (por exemplo, arquivos de texto do Windows terão \ r etc ..), na sua sequência final, você precisará adaptar um pouco mais.
treesAreEverywhere
26
onde esse arquivo de configuração salva no dispositivo real? Não consegui encontrá-lo para verificar :(
Mahdi
4
Eu acho que, fluxos de fechamento deve estar no finalbloco como em resposta @SharkAlley
Yurii K
4
@Kenji, o arquivo é salvo no diretório de arquivos do aplicativo (por exemplo, / data / data / <package_name> /files/config.txt). O processo do aplicativo pode acessá-lo, mas nem todos os processos no sistema operacional. A implementação pode variar dependendo da versão do Android em que o dispositivo é executado. Você pode verificar on-line a implementação do AOSP. Por exemplo, para o Android 8.1_r5: android.googlesource.com/platform/frameworks/base/+/…
vhamon
187

Para aqueles que procuram uma estratégia geral para ler e escrever uma string em um arquivo:

Primeiro, obtenha um objeto de arquivo

Você precisará do caminho de armazenamento. Para o armazenamento interno, use:

File path = context.getFilesDir();

Para o armazenamento externo (cartão SD), use:

File path = context.getExternalFilesDir(null);

Em seguida, crie seu objeto de arquivo:

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

Escreva uma string no arquivo

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

Ou com o Google Guava

Conteúdo da string = Files.toString (file, StandardCharsets.UTF_8);

Leia o arquivo em uma string

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 se você estiver usando o Google Guava

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

Para completar, vou mencionar

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

que não requer bibliotecas, mas avalia 50% a 400% mais lento que as outras opções (em vários testes no meu Nexus 5).

Notas

Para cada uma dessas estratégias, você será solicitado a capturar uma IOException.

A codificação de caracteres padrão no Android é UTF-8.

Se você estiver usando armazenamento externo, precisará adicionar ao seu manifesto:

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

ou

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

A permissão de gravação implica permissão de leitura, portanto você não precisa dos dois.

SharkAlley
fonte
Ok, por exemplo, eu quero que um usuário veja todas as suas postagens e, quando ele for para outra tela e voltar, eu preciso desenhá-lo novamente ou porque está armazenado em cache, ele apenas o retira do cache e apenas o mostra, se apenas não retirá-lo, como faço para adicionar um if condicional a dizer não para consultar meus servidores
Lion789
4
Não faça assim new File(path + "/my-file-name.txt");. Isso desafia muito o senso de File. Use em new File(path, "my-file-name.txt");vez disso.
JimmyB
@HannoBinder O Android sempre roda em cima do Linux, então o separador é garantido como "/". Qual seria o benefício de usar o novo arquivo (caminho, "meu-arquivo-nome.txt") nesse contexto? (Eu sou feliz para atualizar a resposta se há uma razão para isso.)
SharkAlley
1
Fileestá lá por uma razão. No seu caso, você também pode pular Filee fazer new FileInputStream(path + "/my-file-name.txt");, o que eu não recomendo. (O que se pathcontém uma fuga /por exemplo?)
JimmyB
Editado por sua sugestão. Obrigado :)
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
fonte
7
Aplicativo !? o que deveria ser!?
alap
@alap É algo que o @Eugene está usando para recuperar estaticamente o contexto do aplicativo. Ele precisa disso context.getFilesDir(). Você pode apenas substituir ocorrências de new File(context.getFilesDir(), fileName)por um Fileobjeto ou um Stringpassado para funcionar em vez de fileName.
Lorenzo-s
7

Apenas algumas modificações na leitura de string de um método de arquivo para obter mais desempenho

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

verifique o código abaixo.

Lendo de um arquivo no sistema de arquivos.

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

O código abaixo é gravar o arquivo no sistema de arquivos 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;
        }
    }

Eu acho que isso vai te ajudar.

Raj
fonte
3

Sou um pouco iniciante e luto para que isso funcione hoje.

Abaixo está a classe que eu acabei. Funciona, mas eu queria saber como minha solução é imperfeita. De qualquer forma, eu esperava que alguns de vocês, mais experientes, estivessem dispostos a dar uma olhada na minha aula de IO e me dar algumas dicas. Felicidades!

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
fonte
Você não precisa criar um novo arquivo se não houver um arquivo lá.
Rml
1

a primeira coisa que precisamos é das permissões no 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" />

portanto, em uma classe asyncTask Kotlin, tratamos a criação do arquivo

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

    }

Obviamente, se você estiver usando o Android acima da Api 23, deverá processar a solicitação para permitir a gravação na memória do dispositivo. Algo assim

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

em uma atividade, execute a chamada.

  var pathToFileCreated = ""
    val anRW = ReadandWrite().readAndwriteStorage(this,this)
    if(anRW){
        pathToFileCreated =  WriteFile().execute("onTaskComplete").get()
        Log.d("pathToFileCreated",pathToFileCreated)
    }
AllanRibas
fonte
essas permissões de armazenamento interno são inválidas.
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
fonte