273

I want to save a file to the internal storage by getting the text inputted from EditText. Then I want the same file to return the inputted text in String form and save it to another String which is to be used later.

Here's the 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);
            }
        });
    }

I have included comments to help you further analyze my points as to where I want the operations to be done/variables to be used.

GGets
  • 416
  • 6
  • 19
Major Aly
  • 2,570
  • 3
  • 16
  • 19
  • 2
    the question is "how to read/write to/from file?" – Dmitri Gudkov Jan 17 '13 at 10:22
  • Did you consider using the app's preferences to store your strings ? – sdabet Jan 17 '13 at 10:23
  • 5
    BTW, be sure you put permission to the mainfest file, to operate with storage... – Dmitri Gudkov Jan 17 '13 at 10:24
  • 1
    This is my half complete app with many changes to implement. My idea is that the user enter the ID only once at the first run of the app. Then the app will reference that stored ID as many times as the user runs the app. Permissions are all added to the manifest. – Major Aly Jan 17 '13 at 10:28

11 Answers11

400

Hope this might be useful to you.

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

Read 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;
}
larsaars
  • 2,065
  • 3
  • 21
  • 32
R9J
  • 6,605
  • 4
  • 19
  • 25
  • 49
    If the class is not extended from Activity, usage of the "openFileInput()" method should be like this: context.openFileInput() – Behzad Oct 21 '13 at 10:17
  • 14
    Note: The code above works well, but the resulting String will not contain any of the linebreaks from the file. To add linebreaks again, change line "stringBuilder.append(receiveString);" to "stringBuilder.append(receiveString).append("\n");". If you expect other linebreak characters (e.g. Windows text files will have \r etc..), in your final string, you'll have to adapt this a bit more. – treesAreEverywhere Feb 09 '14 at 23:57
  • 33
    where this config file saves in real device? i could not find it to check :( – Mahdi Oct 29 '14 at 06:58
  • how can append to a existing file? – Mahdi Oct 29 '14 at 10:45
  • 5
    I think, closing streams should be in the `final` block as in @SharkAlley answer – Yurii K Jul 29 '15 at 14:41
  • 2
    @saganaut - I was talking about finally block: `finally {inputStream.close();}`. And for finalizers - it's true, you can't rely on them to close resources – Yurii K Sep 07 '16 at 15:03
  • Is this from javax.naming? If so there is no such method as context.openFileInput – Lealo Jul 31 '17 at 00:41
  • @R9J hey, what would be data and context when i need to pass the parameters (calling the method) ? Data i think would be the string i want to write in the file but context what would be, what value should it have? – Fabian Montossi Aug 07 '17 at 02:02
  • @FabianMontossi you can pass `this` if you are in the class which extends `Activity` – R9J Aug 09 '17 at 10:44
  • @R9J and if its from another class would be the name of the class we createf the method, instead of this? – Fabian Montossi Aug 09 '17 at 18:42
  • 7
    @Kenji the file is saved in the app's file directory (i.e. /data/data//files/config.txt). The app's process can access to it but not all processes in the OS. The implementation might differ depending on which android version your device run. You can check the AOSP's implementation online. For example, for android 8.1_r5 : https://android.googlesource.com/platform/frameworks/base/+/android-cts-8.1_r5/core/java/android/app/ContextImpl.java#531 – vhamon May 18 '18 at 12:00
  • You forgot by the way to read the lines, so add .append("\n") to stringBuilder every iteration – larsaars Jan 29 '20 at 21:28
  • 1
    hi, after uninstall app, i got file not. found exception, does this mean file is deleted when uninstall. app? – famfamfam Mar 05 '21 at 09:50
  • The MODE_PRIVATE setting overwrites a file if it already exists. If you want to append data to the file use MODE_APPEND. – antaki93 Jul 29 '23 at 16:58
230

For those looking for a general strategy for reading and writing a string to file:

First, get a file object

You'll need the storage path. For the internal storage, use:

File path = context.getFilesDir();

For the external storage (SD card), use:

File path = context.getExternalFilesDir(null);

Then create your file object:

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

Write a string to the file

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

Or with Google Guava

String contents = Files.toString(file, StandardCharsets.UTF_8);

Read the file to a 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);   

Or if you are using Google Guava

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

For completeness I'll mention

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

which requires no libraries, but benchmarks 50% - 400% slower than the other options (in various tests on my Nexus 5).

Notes

For each of these strategies, you'll be asked to catch an IOException.

The default character encoding on Android is UTF-8.

If you are using external storage, you'll need to add to your manifest either:

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

or

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

Write permission implies read permission, so you don't need both.

Ulala
  • 31
  • 1
  • 6
SharkAlley
  • 11,399
  • 5
  • 51
  • 42
  • Ok for example I want a user to see all his posts, and when he goes to another screen and comes back, do I need to draw it again or because it is cached it just pulls it out from cache and just shows it, if it just does pull it out, how do I add an if conditional to say not to query my servers – Lion789 Mar 08 '14 at 05:55
  • 6
    Don't do it like `new File(path + "/my-file-name.txt");`. This defies much of the sense of `File`. Use `new File(path, "my-file-name.txt");` instead. – JimmyB Aug 10 '15 at 09:13
  • @HannoBinder Android always runs on top of Linux, so the separator is guaranteed to be "/". What would be the benefit of using new File(path, "my-file-name.txt") in this context? (I'm happy to update the answer if there is a reason to.) – SharkAlley Aug 11 '15 at 20:05
  • 2
    `File` is there for a reason. In your case, you could just as well skip `File` and just do `new FileInputStream(path + "/my-file-name.txt");`, which I don't recommend. (What if `path` contains a trailing `/` for example?) – JimmyB Aug 12 '15 at 14:28
  • This answer is outdated and should be removed. – Bart Louwers Jul 17 '23 at 12:44
47
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
  • 59,186
  • 91
  • 226
  • 333
  • 9
    App !? what does it supposed to be !? – alap Jun 08 '14 at 19:26
  • @alap Is something @Eugene is using to retrieve app context statically. He need it for `context.getFilesDir()`. You can just replace occurrences of `new File(context.getFilesDir(), fileName)` with a `File` object or a `String` passed to function instead of `fileName`. – lorenzo-s Feb 17 '15 at 09:06
  • i got file not found exception after unintall app – famfamfam Mar 05 '21 at 09:55
10

The Kotlin way by using builtin Extension function on File

Write: yourFile.writeText(textFromEditText)
Read: yourFile.readText()

Darshan
  • 4,020
  • 2
  • 18
  • 49
  • Users should make sure how to properly define a readable/writable to use those functions, specially under Android platform. – Lucas Sousa Apr 29 '23 at 10:05
8

Just a a bit modifications on reading string from a file method for more performance

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
  • 268
  • 3
  • 10
7

check the below code.

Reading from a file in the 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;
        }
    }

below code is to write the file in to internal filesystem.

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

I think this will help you.

Raj
  • 1,843
  • 2
  • 21
  • 47
5

I'm a bit of a beginner and struggled getting this to work today.

Below is the class that I ended up with. It works but I was wondering how imperfect my solution is. Anyway, I was hoping some of you more experienced folk might be willing to have a look at my IO class and give me some tips. Cheers!

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
  • 51
  • 1
  • 3
4

the first thing we need is the permissions in AndroidManifest.xml

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

so in an asyncTask Kotlin class, we treat the creation of the 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)
            }
        }

    }

Of course if you are using Android above Api 23, you must handle the request to allow writing to device memory. Something like this

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

then in an activity, execute the call.

  var pathToFileCreated = ""
    val anRW = ReadandWrite().readAndwriteStorage(this,this)
    if(anRW){
        pathToFileCreated =  WriteFile().execute("onTaskComplete").get()
        Log.d("pathToFileCreated",pathToFileCreated)
    }
AllanRibas
  • 678
  • 5
  • 14
3

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
    }
}
Community
  • 1
  • 1
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
2

We can use this code to write String to a file

public static void writeTextToFile(final String filename, final String data) {
    File file = new File(filename);
    try {
        FileOutputStream stream = new FileOutputStream(file);
        stream.write(data.getBytes());
        stream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Then in the Main code, we use this, for example

writeTextToFile(getExternalFilesDir("/").getAbsolutePath() + "/output.txt", "my-example-text");

After that, check the file at Android/data/<package-name>/files.

dqthe
  • 683
  • 5
  • 8
-2

In kotlin, The easiest way to append to a text file in kotlin:

val directory = File(context.filesDir, "LogsToSendToNextMunich").apply { 
    mkdirs() 
}
val file = File(directory,"Logs.txt")
file.appendText("You new text")

If you want to just write to the file:

yourFile.writeText("You new text")

writing anything to the files, using bytes:

FileOutputStream(file).use {
    it.write("Some text for example".encodeToByteArray()) 
}
Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38
  • question is tagged java and OP uses java – masterxilo Jun 17 '23 at 13:58
  • 1
    @masterxilo while I'm not sure about you, but I think all java questions in Android, deserve a new Kotlin answer as well. and its better to down vote an answer if you think it doesn't where work, where in android, you can use kotlin along side java. So there is nothing wrong here :) Happy coding java – Amin Keshavarzian Jun 19 '23 at 14:11