在Android中从/向文件读取/写入字符串

Posted

技术标签:

【中文标题】在Android中从/向文件读取/写入字符串【英文标题】:Read/Write String from/to a File in Android 【发布时间】:2012-12-31 20:35:24 【问题描述】:

我想通过获取从 EditText 输入的文本将文件保存到内部存储。然后我希望同一个文件以 String 形式返回输入的文本并将其保存到另一个 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);
            
        );
    

我已包含 cmets 以帮助您进一步分析我的观点,即我希望在何处完成操作/使用变量。

【问题讨论】:

问题是“如何读取/写入文件?” 您是否考虑过使用应用程序的首选项来存储您的字符串? 顺便说一句,请确保您授予 mainfest 文件的权限,以使用存储... 这是我的半完整应用程序,需要实施许多更改。我的想法是用户在应用程序第一次运行时只输入一次 ID。然后,应用程序将在用户运行应用程序时多次引用该存储的 ID。权限都添加到清单中。 【参考方案1】:

在 kotlin 中追加到文本文件的最简单方法:

val directory = File(context.filesDir, "LogsToSendToNextMunich").apply  
    mkdirs() 

val file = File(directory,"Logs.txt")
file.appendText("You new text")

如果您只想写入文件:

yourFile.writeText("You new text")

使用字节向文件写入任何内容:

FileOutputStream(file).use 
    it.write("Some text for example".encodeToByteArray()) 

【讨论】:

【参考方案2】:

我们首先需要的是 AndroidManifest.xml 中的权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_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)
            
        

    

当然,如果您使用的是 Api 23 以上的 Android,您必须处理请求以允许写入设备内存。像这样的

    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)
    

【讨论】:

那些内部存储权限无效。【参考方案3】:

File上使用内置扩展函数的Kotlin方式

写: yourFile.writeText(textFromEditText)读: yourFile.readText()

【讨论】:

【参考方案4】:

希望这对你有用。

写入文件:

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;

【讨论】:

如果类不是从Activity扩展的,“openFileInput()”方法的用法应该是这样的:context.openFileInput() 注意:上面的代码运行良好,但生成的字符串不会包含文件中的任何换行符。要再次添加换行符,请更改行“stringBuilder.append(receiveString);”到 "stringBuilder.append(receiveString).append("\n");"。如果您期望其他换行符(例如 Windows 文本文件将有 \r 等),在您的最终字符串中,您将不得不更多地调整它。 这个配置文件在真实设备中保存在哪里?我找不到它来检查:( 我认为,关闭流应该在@SharkAlley 回答中的final 块中 @Kenji 文件保存在应用程序的文件目录中(即/data/data//files/config.txt)。应用程序的进程可以访问它,但不是操作系统中的所有进程。实施可能会有所不同,具体取决于您的设备运行的 android 版本。您可以在线查看 AOSP 的实施情况。例如,对于 android 8.1_r5:android.googlesource.com/platform/frameworks/base/+/…【参考方案5】:

科特林

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
    

【讨论】:

【参考方案6】:
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();

【讨论】:

应用程序!?它应该是什么!? @alap 是 @Eugene 用来静态检索应用程序上下文的东西。他需要context.getFilesDir()。您可以将出现的new File(context.getFilesDir(), fileName) 替换为File 对象或传递给函数的String 而不是fileName 卸载应用后发现文件未找到异常【参考方案7】:

对于那些正在寻找将字符串读取和写入文件的一般策略的人:

首先,获取一个文件对象

您需要存储路径。对于内部存储,请使用:

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(file, 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"/>

写权限意味着读权限,所以你不需要两者。

【讨论】:

好吧,例如我希望用户看到他的所有帖子,当他转到另一个屏幕并返回时,我是否需要再次绘制它或者因为它被缓存了它只是从缓存并显示它,如果它只是将其拉出,我如何添加一个 if 条件来表示不查询我的服务器 不要像new File(path + "/my-file-name.txt");那样做。这违背了File 的大部分意义。请改用new File(path, "my-file-name.txt"); @HannoBinder Android 始终运行在 Linux 之上,因此分隔符保证为“/”。在这种情况下使用 new File(path, "my-file-name.txt") 有什么好处? (如果有理由,我很乐意更新答案。) File 是有原因的。在你的情况下,你也可以跳过File,直接做new FileInputStream(path + "/my-file-name.txt");,我不推荐这样做。 (例如,如果path 包含一个尾随/ 怎么办?) 根据您的建议进行了编辑。谢谢:)【参考方案8】:

我是一个初学者,今天很难让它发挥作用。

以下是我最终学习的课程。它有效,但我想知道我的解决方案有多不完美。无论如何,我希望你们中一些更有经验的人可能愿意看看我的 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();
        
    

【讨论】:

如果没有文件,则不需要创建新文件。【参考方案9】:

对从文件方法读取字符串稍作修改以提高性能

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;

【讨论】:

【参考方案10】:

检查下面的代码。

从文件系统中的文件中读取。

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;
        
    

我想这会对你有所帮助。

【讨论】:

以上是关于在Android中从/向文件读取/写入字符串的主要内容,如果未能解决你的问题,请参考以下文章

android 如何读写文件?

c语言 怎么读文件中的汉字

python实现读写txt文件

Android 怎样在应用程序中向文件里写入数据?

如何在 Flutter 中从 firebase 存储读取和写入文本文件?

在 Node JS 中从不同的“会话”读取/写入相同的文件内容是不是有风险?