Читання / запис рядків з / у файл в Android


213

Я хочу зберегти файл у внутрішній пам’яті, отримавши текст, введений з EditText. Тоді я хочу, щоб той самий файл повернув введений текст у формі String і зберег у інший рядок, який повинен бути використаний пізніше.

Ось код:

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

Я включив коментарі, щоб допомогти вам далі проаналізувати мої моменти щодо того, де я хочу зробити операції / використовувати змінні.


2
питання "як читати / записувати в / з файлу?"
Дмитро Гудков

Чи планували ви використовувати параметри програми для зберігання своїх рядків?
sdabet

4
BTW, будьте впевнені, що ви поклали дозвіл на файл mainfest, щоб працювати зі сховищем ...
Дмитро Гудков,

Це моя наполовину повна програма з багатьма змінами, які потрібно здійснити. Моя ідея полягає в тому, що користувач вводить ідентифікатор лише один раз при першому запуску програми. Тоді додаток посилається на цей збережений ідентифікатор стільки разів, скільки користувач запускає його. До маніфесту додаються всі дозволи.
майор Алі

Відповіді:


334

Сподіваюся, це може бути корисним для вас.

Написати файл:

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

Файл читання:

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
Якщо клас не поширюється на Діяльність, використання методу "openFileInput ()" має бути таким: context.openFileInput ()
Бехзад

11
Примітка: Код, описаний вище, працює добре, але результуюча рядок не буде містити жодного з перерив рядків у файлі. Щоб знову додати рядкові перерви, змініть рядок "stringBuilder.append (acceptString);" до "stringBuilder.append (получиString) .append (" \ n ");". Якщо ви очікуєте, що інші символи рядка (наприклад, текстові файли Windows матимуть і т. Д.), В останньому рядку вам доведеться трохи більше адаптувати це.
дереваAreEverywhere

26
де цей конфігураційний файл зберігається в реальному пристрої? я не міг знайти його для перевірки :(
Махді

4
Я думаю, закриття потоків повинно бути в finalблоці, як у відповіді @SharkAlley
Юрій К

4
@Kenji файл зберігається у каталозі файлів програми (тобто / data / data / <package_name> /files/config.txt). Процес програми може отримати доступ до нього, але не всі процеси в ОС. Реалізація може відрізнятися залежно від того, в якій версії Android працює ваш пристрій. Ви можете перевірити реалізацію AOSP в Інтернеті. Наприклад, для android 8.1_r5: android.googlesource.com/platform/frameworks/base/+/…
vhamon

187

Для тих, хто шукає загальну стратегію читання та написання рядка для файлу:

Спочатку знайдіть об’єкт файлу

Вам знадобиться шлях для зберігання. Для внутрішнього зберігання використовуйте:

File path = context.getFilesDir();

Для зовнішнього сховища (SD-карта) використовуйте:

File path = context.getExternalFilesDir(null);

Потім створіть свій об’єкт файлу:

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

Введіть рядок у файл

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

Або з Google Guava

Зміст рядка = Files.toString (файл, StandardCharsets.UTF_8);

Прочитайте файл у рядку

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

Або якщо ви використовуєте Google Guava

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

Для повноти згадаю

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

що не вимагає бібліотек, але показники на 50% - на 400% повільніше, ніж інші параметри (у різних тестах на моєму Nexus 5).

Примітки

Для кожної з цих стратегій вам буде запропоновано ввести IOException.

За замовчуванням кодування символів на Android - UTF-8.

Якщо ви використовуєте зовнішню пам’ять, вам потрібно буде додати до маніфесту:

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

або

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

Дозвіл на запис передбачає дозвіл на читання, тому вам не потрібно обох.


Добре, наприклад, я хочу, щоб користувач бачив усі його публікації, і коли він переходить на інший екран і повертається, чи потрібно мені малювати його ще раз або тому, що він кешований, він просто витягує його з кеша і просто показує, якщо він просто витягніть його, як додати, якщо умовно сказати, щоб не запитувати мої сервери
Lion789,

4
Не роби так new File(path + "/my-file-name.txt");. Це багато чого не сприймає File. Використовуйте new File(path, "my-file-name.txt");замість цього.
JimmyB

@HannoBinder Android завжди працює над Linux, тому роздільник гарантовано є "/". Яка була б користь від використання нового файлу (шлях, "my-file-name.txt") у цьому контексті? (Я радий оновити відповідь, якщо є причина.)
SharkAlley

1
Fileє чомусь. У вашому випадку ви можете так само пропустити Fileі просто зробити new FileInputStream(path + "/my-file-name.txt");, що я не рекомендую. (Що робити, якщо, наприклад, pathміститься трейлінг /?)
JimmyB

Відредаговано за вашою пропозицією. Дякую :)
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
Додаток !? що це повинно бути !?
алап

@alap Щось @Eugene використовує для статичного пошуку контексту програми. Йому це потрібно context.getFilesDir(). Ви можете просто замінити випадки new File(context.getFilesDir(), fileName)на Fileоб'єкт або Stringпередані функції замість fileName.
lorenzo-s

7

Просто невеликі модифікації для читання рядка з файлового методу для більшої продуктивності

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

перевірте наведений нижче код.

Читання з файлу у файловій системі.

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

нижче код - це записати файл у внутрішню файлову систему.

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

Я думаю, що це вам допоможе.


3

Я трохи початківець і боровся за те, щоб сьогодні це працювати.

Нижче - клас, в якому я закінчив. Це працює, але мені було цікаво, наскільки недосконале моє рішення. У будь-якому випадку, я сподівався, що хтось із вас, більш досвідчений народ, може, захоче поглянути на мій клас IO і дати мені поради. Ура!

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

Вам не потрібно створювати новий файл, якщо в ньому немає файлу.
rml

1

перше, що нам потрібно - це дозволи в 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" />

тож у класі asyncTask Kotlin ми ставимося до створення файлу

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

    }

Звичайно, якщо ви користуєтесь Android вище Api 23, вам слід обробити запит, щоб дозволити запис у пам'ять пристрою. Щось на зразок цього

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

потім у діяльності виконайте виклик.

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

ці внутрішні дозволи на зберігання недійсні.
Лерк

0

Котлін

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
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.