原汁原味的安卓文件存储(数据存储系列)

本文正在参加「金石计划 . 瓜分6万现金大奖」

前言

上一篇我们简单的了解了安卓数据存储并初识了文件存储这个技术(Re:从零开始的安卓数据存储学习生活(开篇) - 掘金 (juejin.cn))。本篇将进一步看看文件存储是怎么用的。

正篇

概述

其实文件存储是安卓中最基本的数据存储方式,所以说它原汁原味也不过分,它不会对存储的内容进行任何格式化处理,用它存储的数据都是原封不动的保存在文件中。
但这样也就使得这种方式更适合存储一些比较简单的文本数据或是二进制数据,其实如果真的想用文件存储的方式去保存一些比较复杂的结构化数据,也可以定义一套自己的格式规范,以方便将数据从文件中再次解析出来。
本篇使用一个完整的例子来说明文件存储的一些基本用法,暂不对相关复杂存储说明。

存文件

本例子是通过文件存储输入框输入的内容来实现下次重新启动APP的输入框中仍然可以显示所输入内容,这也是我们很多APP上表现的输入历史记录一样,不过我在业务中一般还是用数据存储的第二种方式-SharedPreferences存储。

我们首先在activity_main.xml布局中添加一个EditText,作为我们的输入框用来输入存储内容,代码如下:

<EditText
    android:id="@+id/editText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Please write something here"
    />
复制代码

接着在onDestroy()方法中我们调用save()方法,save()方法即我们利用文件存储存入数据的方法,这样我们就能在Activity结束前把我们输入的东西存入文件中,代码如下:

override fun onDestroy() {
    super.onDestroy()
    val inputText = editText.text.toString()
    save(inputText)
}
复制代码
private fun save(inputText : String) {
    try {
        val output = openFileOutput("data", Context.MODE_PRIVATE)
        val write = BufferedWriter(OutputStreamWriter(output))
        write.use {
            it.write(inputText)
        }
    } catch (e : IOException) {
        e.printStackTrace()
    }
}
复制代码

这个时候我们可以在AS的Device File Explorer中找到文件,如下图:

image.png

在/data/data/com.example.filepersistencetest找到data文件 image.png image.png

打开后可以看到就是刚刚退出Activity时候输入的数据,说明文件已经成功保存。 image.png

取出数据

对应的我们也需要在用的时候再次取出数据,于是我们需要利用Context类中提供的另一个方法-openFileInput()方法,使用方法如下,我们将其封装为load方法用于在onCreate方法调用,这样打开的APP就能获取到之前输入的数据并加载出来:

//取出文件中所保存内容
private fun load() : String {
    //把文件取出的数据一行行拼接在StringBuilder对象当中,用于返回内容(String)
    val content = StringBuilder()
    try {
        //获取FileInputStream对象
        val input = openFileInput("data")
        //构建BufferedReader对象
        val reader = BufferedReader(InputStreamReader(input))
        //读取文件内容
        reader.use {
            //Kotlin提供的一个内置扩展函数,可以将读到的每行内容都回调到Lambda表达式中,然后在Lambda表达式中完成拼接逻辑
            reader.forEachLine {
                content.append(it)
            }
        }
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return content.toString()
}
复制代码

该方法接受要读取的文件名作为参数,系统自动到/data/data/<package name>/files目录下加载对应文件,返回FileInputStream对象,我们再通过流的方式就可以将数据读取出来。

image.png onCreate方法中调用的代码:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val inputText = load()
    //数据不为空则将内容填充到EditText中
    if (inputText.isNotEmpty()) {
        editText.setText(inputText)
        //光标(焦点)位置移到文字末
        editText.setSelection(inputText.length)
        //还原成功提示
        Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show()
    }
}
复制代码

总结

文件存储不太适合保存比较复杂的结构型数据,下一篇将探讨一下我感觉更重要的Sp存储,这个存储方式真的在工作中频繁用到,谢谢各位观看,敬请期待下一篇!

猜你喜欢

转载自juejin.im/post/7166633519274426381