Android Kotlin语言下的文件存储

目录

将数据存储到文件中

创建文件和保存数据

读取文件

SharedPreferences存储

存储数据到SharedPreferences中

Context类中的getSharedPreferences()方法

Activity类中的getPreferences()方法

从SharedPreferences中读取数据

SQLite数据库存储

创建数据库

调用数据库

操作数据库

升级数据库


将数据存储到文件中

创建文件和保存数据

Context类中提供了一个openFileOutput()方法,可以用于将数据存储到指定的文件中。这个方法接收两个参数:第一个参数是文件名,在文件创建的时候使用,注意这里指定的文件名不可以包含路径,因为所有的文件都默认存储到/data/data/<package name>/files/目录下;第二个参数是文件的操作模式,主要有MODE_PRIVATEMODE_APPEND两种模式可选,默认是MODE_PRIVATE,表示当指定相同文件名的时候,所写入的内容将会覆盖原文件中的内容,而MODE_APPEND则表示如果该文件已存在,就往文件里面追加内容,不存在就创建新文件。其实文件的操作模式本来还有另外两种:MODE_WORLD_READABLEMODE_WORLD_WRITEABLE。这两种模式表示允许其他应用程序对我们程序中的文件进行读写操作,不过由于这两种模式过于危险,很容易引起应用的安全漏洞,已在Android 4.2版本中被废弃。

openFileOutput()方法返回的是一个FileOutputStream对象,得到这个对象之后就可以使用Java流的方式将数据写入文件中了。以下是一段简单的代码示例,展示了如何将一段文本内容保存到文件中:

    fun saveFile(saveString: String) {val output = openFileOutput("fileName", Context.MODE_PRIVATE)val writer = BufferedWriter(OutputStreamWriter(output))writer.use {it.write(saveString)}}

这里通过openFileOutput()方法能够得到一个FileOutputStream对象,然后借助它构建出一个OutputStreamWriter对象,接着再使用OutputStreamWriter构建出一个BufferedWriter对象,这样你就可以通过BufferedWriter将文本内容写入文件中了。

注意,这里还使用了一个use函数,这是Kotlin提供的一个内置扩展函数。它会保证在Lambda表达式中的代码全部执行完之后自动将外层的流关闭,这样就不需要我们再编写一个finally语句,手动去关闭流了,是一个非常好用的扩展函数。

另外,Kotlin是没有异常检查机制(checked exception)的。这意味着使用Kotlin编写的所有代码都不会强制要求你进行异常捕获或异常抛出。即使你不写try catch代码块,在Kotlin中依然可以编译通过。

读取文件

类似于将数据存储到文件中,Context类中还提供了一个openFileInput()方法,用于从文件中读取数据。这个方法要比openFileOutput()简单一些,它只接收一个参数,即要读取的文件名,然后系统会自动到/data/data/<package name>/files/目录下加载这个文件,并返回一个FileInputStream对象,得到这个对象之后,再通过流的方式就可以将数据读取出来了。

以下是一段简单的代码示例,展示了如何从文件中读取文本数据:

    fun loadFile(): String {val stringBuilder = StringBuilder()val input = openFileInput("fileName")val reader = BufferedReader(InputStreamReader(input))reader.use {reader.forEachLine {stringBuilder.append(it)}}return stringBuilder.toString()}

在这段代码中,首先通过openFileInput()方法获取了一个FileInputStream对象,然后借助它又构建出了一个InputStreamReader对象,接着再使用InputStreamReader构建出一个BufferedReader对象,这样我们就可以通过BufferedReader将文件中的数据一行行读取出来,并拼接到StringBuilder对象当中,最后将读取的内容返回就可以了。

注意,这里从文件中读取数据使用了一个forEachLine函数,这也是Kotlin提供的一个内置扩展函数,它会将读到的每行内容都回调到Lambda表达式中,我们在Lambda表达式中完成拼接逻辑即可。

SharedPreferences存储

存储数据到SharedPreferences中

要想使用SharedPreferences存储数据,首先需要获取SharedPreferences对象。Android中主要提供了以下两种方法用于得到SharedPreferences对象。

  1. Context类中的getSharedPreferences()方法

    此方法接收两个参数:第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/data/data/<package name>/shared_prefs/目录下的;第二个参数用于指定操作模式,目前只有默认的MODE_PRIVATE这一种模式可选,它和直接传入0的效果是相同的,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。其他几种操作模式均已被废弃,MODE_WORLD_READABLEMODE_WORLD_WRITEABLE这两种模式是在Android 4.2版本中被废弃的,MODE_MULTI_PROCESS模式是在Android 6.0版本中被废弃的。

  2. Activity类中的getPreferences()方法

    这个方法和Context中的getSharedPreferences()方法很相似,不过它只接收一个操作模式参数,因为使用这个方法时会自动将当前Activity的类名作为SharedPreferences的文件名。

    得到了SharedPreferences对象之后,就可以开始向SharedPreferences文件中存储数据了,主要可以分为3步实现。

    (1) 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象。

    (2) 向SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用putBoolean()方法,添加一个字符串则使用putString()方法,以此类推。

    (3) 调用apply()方法将添加的数据提交,从而完成数据存储操作。

 代码示例如下

    fun saveSharedPreferences(saveString: String){val edit = getSharedPreferences("fileName",Context.MODE_PRIVATE).edit()edit.putString("editName","editValue")edit.apply()}

从SharedPreferences中读取数据

SharedPreferences对象中提供了一系列的get方法,用于读取存储的数据,每种get方法都对应了SharedPreferences.Editor中的一种put方法,比如读取一个布尔型数据就使用getBoolean()方法,读取一个字符串就使用getString()方法。这些get方法都接收两个参数:第一个参数是键,传入存储数据时使用的键就可以得到相应的值了;第二个参数是默认值,即表示当传入的键找不到对应的值时会以什么样的默认值进行返回。

代码示例如下

    fun loadSharedPreferences(): String {val sharedPreferences = getSharedPreferences("fileName", Context.MODE_PRIVATE)return sharedPreferences.getString("editName", "defValue")!!}

SQLite数据库存储

创建数据库

Android为了让我们能够更加方便地管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类可以非常简单地对数据库进行创建和升级。既然有好东西可以直接使用,那我们自然要尝试一下了,下面我就对SQLiteOpenHelper的基本用法进行介绍。

首先,你要知道SQLiteOpenHelper是一个抽象类,这意味着如果我们想要使用它,就需要创建一个自己的帮助类去继承它。SQLiteOpenHelper中有两个抽象方法:onCreate()onUpgrade()。我们必须在自己的帮助类里重写这两个方法,然后分别在这两个方法中实现创建和升级数据库的逻辑。

SQLiteOpenHelper中还有两个非常重要的实例方法:getReadableDatabase()getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则要创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式打开数据库,而getWritableDatabase()方法则将出现异常。

SQLiteOpenHelper中有两个构造方法可供重写,一般使用参数少一点的那个构造方法即可。这个构造方法中接收4个参数:第一个参数是Context,这个没什么好说的,必须有它才能对数据库进行操作;第二个参数是数据库名,创建数据库时使用的就是这里指定的名称;第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null即可;第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。构建出SQLiteOpenHelper的实例之后,再调用它的getReadableDatabase()getWritableDatabase()方法就能够创建数据库了,数据库文件会存放在/data/data/<package name>/databases/目录下。此时,重写的onCreate()方法也会得到执行,所以通常会在这里处理一些创建表的逻辑。

我们建立一个代码示例如下:

class MyDatabaseHelper(private val context: Context,private val databaseName: String,val version: Int
) : SQLiteOpenHelper(context, databaseName, null, version) {private val createTable = "create table tableName(id integer primary key autoincrement, " +"key1 text," +"key2 real," +"key3 integer)"override fun onCreate(db: SQLiteDatabase?) {db?.execSQL(createTable)}override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {}
}

调用数据库

val myDatabaseHelper =MyDatabaseHelper(this,"databaseName",1)
myDatabaseHelper.writableDatabase

操作数据库

val myDatabaseHelper = MyDatabaseHelper(this, "databaseName", 1)
val db = myDatabaseHelper.writableDatabase
val value1 = ContentValues().apply {put("key1", "111")put("key2", 1.1)put("key3", 1)
}
db.insert("tableName", null, value1)val value2 = ContentValues().apply {put("key1", "222")put("key2", 2.2)put("key3", 2)
}
db.insert("tableName", null, value2)
db.delete(tableName, "key2 = ? and key3 = ? ", arrayOf("2.2","2"))
val value3 = ContentValues().apply {put("key1", "444")}
db.update(tableName, value3, "key2 = ?", arrayOf("1.1"))
        val course = db.query(tableName, null, null, null, null, null, null)if (course.moveToFirst()) {do {println(course.getString(course3.getColumnIndex("key1")))println(course.getString(course.getColumnIndex("key2")))println(course.getString(course.getColumnIndex("key3")))} while (course.moveToNext())}course.close()

升级数据库

在MyDatabaseHelper类中,我们还有一个onUpgrade的方法没有使用,这个方法就是用来升级数据库的,当我们需要升级数据库时,改写MyDatabaseHelper的version,让它大于我们直接传入的数,这样就会自动调用onUpgrade,示例代码如下:

val myDatabaseHelper = MyDatabaseHelper(this, databaseName, 2)

然后我们在onUpgrade方法中编写升级逻辑,代码如下:

class MyDatabaseHelper(private val context: Context,private val databaseName: String,val version: Int
) : SQLiteOpenHelper(context, databaseName, null, version) {private val createTable = "create table tableName(id integer primary key autoincrement, " +"key1 text," +"key2 real," +"key3 integer)"private val createTable2 = "create table tableName2(id integer primary key autoincrement, " +"key1 text," +"key2 real," +"key3 integer)"override fun onCreate(db: SQLiteDatabase?) {db?.execSQL(createTable)db?.execSQL(createTable2)}override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {if (oldVersion<=1){db?.execSQL(createTable2)}}
}

当原来的版本是1时,我们就创建表2,不然就执行onCreate方法,创建表1表2。如果后续我们需要再表1中增加一个字段  tableName_id,那么我们将传入的version改成3,再在onUpgrade方法中编写如下代码:

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {if (oldVersion<=1){db?.execSQL(createTable2)}if (oldVersion<=2){db?.execSQL("alter table tableName add column tableName_id integer")}}

这样我们就能在表1中新增一个tableName_id字段了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/209321.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java导出word

原文地址 传入的值不能为null,否则会报错&#xff0c;IXDocReport 有自己的判null规则&#xff0c;比较麻烦&#xff0c;建议代码直接把null替换成"" public void exportWord1(WeeklyMeetDataDto dto, HttpServletResponse response) {ServletOutputStream downLoad…

Ignis - Interactive Fire System

Ignis - 点火、蔓延、熄灭、定制! 全方位火焰系统。 这个插件在21年的项目中使用过很好用值使用概述 想玩火吗?如果想的话,那么Ignis就是你的最佳工具。有了Ignis,你可以把任何物体、植被或带皮带骨的网状物转换为可燃物体,它就会自动着火。然后,火焰可以蔓延,点燃其他物…

Java 一对多

前言 Internet 协议集支持一个无连接的传输协议&#xff0c;该协议称为用户数据报协议&#xff08;UDP&#xff0c;User Datagram Protocol&#xff09;。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。 此代码就是基于UDP协议编写。 通常把一对多的…

【docker 】centOS 安装docker

官网 docker官网 github源码 卸载旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 安装软件包 yum install -y yum-utils \device-mapper-persistent-data…

【优选算法系列】【专题二滑动窗口】第四节.30. 串联所有单词的子串和76. 最小覆盖子串

文章目录 前言一、串联所有单词的子串 1.1 题目描述 1.2 题目解析 1.2.1 算法原理 1.2.2 代码编写 1.2.3 题目总结二、最小覆盖子串 2.1 题目描述 2.2 题目解析 2.2.1 算法原理 2.2.2 代码编写 …

【Docker】进阶之路:(四)操作容器

【Docker】进阶之路&#xff1a;&#xff08;四&#xff09;Docker容器 容器的生命周期创建容器docker createdocker run 管理容器查看运行的容器&#xff1a;查看所有容器&#xff1a; 启动与终止启动容器终止容器 进入容器docker attachdocker exec 导出和导入导出导入 容器的…

浅谈5G基站节能及数字化管理解决方案的设计与应用-安科瑞 蒋静

截至2023年10月&#xff0c;我国5G基站总数达321.5万个&#xff0c;占全国通信基站总数的28.1%。然而&#xff0c;随着5G基站数量的快速增长&#xff0c;基站的能耗问题也逐渐日益凸显&#xff0c;基站的用电给运营商带来了巨大的电费开支压力&#xff0c;降低5G基站的能耗成为…

actitivi自定义属性(二)

声明&#xff1a;此处activiti版本为6.0 此文章介绍后端自定义属性解析&#xff0c;前端添加自定义属性方法连接&#xff1a;activiti自定义属性&#xff08;一&#xff09;_ruoyi activiti自定义标题-CSDN博客 1、涉及到的类如下&#xff1a; 简介&#xff1a;DefaultXmlPar…

在 JavaScript 中导入和导出 Excel XLSX 文件:SpreadJS

在 JavaScript 中导入和导出 Excel XLSX 文件 2023 年 12 月 5 日 使用 MESCIUS 的 SpreadJS 将完整的 JavaScript 电子表格添加到您的企业应用程序中。 SpreadJS 是一个完整的企业 JavaScript 电子表格解决方案&#xff0c;用于创建财务报告和仪表板、预算和预测模型、科学、工…

【华为OD】给定一个只包括 ‘(‘,‘)‘,‘{‘,‘}‘,‘[‘,‘]‘ 的字符串

给定一个只包括 (,),{,},[,] 的字符串 s , 判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 示例 1 : 输入:s="()" 输出 : true 示例 2 :

图的搜索(一):广度优先搜索算法和深度优先搜索算法

图的搜索&#xff08;一&#xff09;&#xff1a;广度优先搜索算法和深度优先搜索算法 本章主要记录了图的搜索算法&#xff0c;和可以解决图的基本问题——最短路径问题的算法。本章主要对图搜索的相关算法进行了介绍&#xff1a;广度优先搜索算法、深度优先搜索算法。 下一…

公网域名如何解析到内网IP服务器——快解析域名映射外网访问

在本地搭建主机应用后&#xff0c;由于没有公网IP或没有公网路由权限&#xff0c;在需要发布互联网时&#xff0c;就需要用到外网访问内网的一些方案。由于内网IP在外网不能直接访问&#xff0c;通常就用通过外网域名来访问内网的方法。那么&#xff0c;公网域名如何解析到内网…

Tmux中使用Docker报错 - 解决方案

问题 进入Tmux会话后&#xff0c;在其中使用Docker可能会出现如下报错&#xff1a; Got permission denied while trying to connect to the Docker ……解决方案 退出tmux会话: tmux detach在tmux会话外部杀掉tmux进程&#xff1a; pkill -f tmux重新进入tmux&#xff1a…

权威认证!景联文科技入选杭州市2023年第二批省级“专精特新”中小企业认定名单

为深入贯彻党中央国务院和省委省政府培育专精特新的决策部署&#xff0c;10月7日&#xff0c;杭州市经济和信息化委员会公示了2023年杭州“专精特新”企业名单&#xff08;第二批&#xff09;。 根据工业和信息化部《优质中小企业梯度培育管理暂行办法》&#xff08;工信部企业…

【Vue3+Ts项目】硅谷甄选 — 路由配置+登录模块+layout组件+路由鉴权

一、路由配置 项目一共需要4个一级路由&#xff1a;登录&#xff08;login&#xff09;、主页&#xff08;home&#xff09;、404、任意路由&#xff08;重定向到404&#xff09;。 1.1 安装路由插件 pnpm install vue-router 1.2 创建路由组件 在src目录下新建views文件…

Graphpad Prism10.1.0 安装教程 (含Win/Mac版)

GraphPad Prism GraphPad Prism是一款非常专业强大的科研医学生物数据处理绘图软件&#xff0c;它可以将科学图形、综合曲线拟合&#xff08;非线性回归&#xff09;、可理解的统计数据、数据组织结合在一起&#xff0c;除了最基本的数据统计分析外&#xff0c;还能自动生成统…

Python:核心知识点整理大全8-笔记

目录 ​编辑 4.5 元组 4.5.1 定义元组 dimensions.py 4.5.2 遍历元组中的所有值 4.5.3 修改元组变量 4.6 设置代码格式 4.6.1 格式设置指南 4.6.2 缩进 4.6.3 行长 4.6.4 空行 4.6.5 其他格式设置指南 4.7 小结 第5章 if语句 5.1 一个简单示例 cars.py 5.2 条…

现代皮质沙发模型材质编辑

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

线性容器(QByteArray、QString、QList模板类)、堆栈窗体

QT 线性容器 点击查看&#xff1a;字符和字节的区别&#xff0c;ASCII、Unicode 和 UTF-8 编码的区别。&#xff08;&#x1f448; 安全链接&#xff0c;放心跳转&#xff09; QByteArray 思考&#xff1a;char buf[6] “hello”; 如果 C 语言中要利用 buf 内容重新生成 “…

学生备考使用台灯到底好不好?公认好用的护眼台灯推荐

在现代生活中&#xff0c;许多学生的学习压力越来越大&#xff0c;面临的近视几率也越来越大&#xff0c;特别是初中生&#xff0c;眼睛发育还未完全&#xff0c;使用不恰当的灯光也会对眼睛造成损害&#xff0c;特别是护眼台灯。虽然护眼台灯在功能上能够提供充足、柔和的光线…