Java的文件处理用到了io库java.io,该库虽然功能强大,但是与文件内容的交互还得通过输入输出流中转,致使文件读写操作颇为繁琐。因此,开发者通常得自己重新封装一个文件存取的工具类,以便在日常开发中调用。下面是一个文件工具类的简单Java代码:

public class FileUtil {

	//保存文本文件
public static void saveText(String path, String txt) {
try {
FileOutputStream fos = new FileOutputStream(path);
fos.write(txt.getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
} //读取文本文件
public static String openText(String path) {
String readStr = "";
try {
FileInputStream fis = new FileInputStream(path);
byte[] b = new byte[fis.available()];
fis.read(b);
readStr = new String(b);
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
return readStr;
}
}

从上述代码看到,仅仅是文本文件的内容保存和读取,就得规规矩矩写这么多行代码,并且还不太容易理解,对于新手来说着实不够友好。哪里有痛点,哪里就有优化,所以Kotlin在文件API这块也下了一番功夫,它以Java的io库为基础,利用扩展函数,添加了一些常用的文件内容读写方法,并且往往是一行代码便搞定功能,绝不拖泥带水。

比如把一段文本写入文本文件,只消调用File对象的writeText方法,即可实现写入文本的功能。真的只要一行代码,就像下面这样:

    //把文本写入文件
File(file_path).writeText(content)

如此简洁又好用的代码,想必是许多开发者梦寐以求的。当然了,Kotlin同样支持其它格式的数据写入,前面的writeText方法是覆盖写入文本,如果要往源文件追加文本,则可调用appendText方法。另外像图片等二进制格式的文件,可通过字节数组的形式写入文件,Kotlin提供了writeBytes方法用于覆盖写入字节数组,也提供了appendBytes方法用于追加字节数组。不过由于图像存储比较特殊,牵涉到压缩格式与压缩质量,因此还得通过输出流来处理(这是Bitmap的compress方法要求的),具体的图片文件写入代码如下所示:

    fun saveImage(path: String, bitmap: Bitmap) {
try {
val file = File(path)
//outputStream获取文件的输出流对象
//writer获取文件的Writer对象
//printWriter获取文件的PrintWriter对象
val fos: OutputStream = file.outputStream()
//压缩格式为JPEG图像,压缩质量为80%
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos)
fos.flush()
fos.close()
} catch (e: Exception) {
e.printStackTrace()
}
}

看过了文件的写入操作,再来看看文件的读取操作。有了writeText方法带好头,Kotlin又提供了以下几个好看且好用的文件内容读取方法:

readText : 读取文本形式的文件内容。
readLines : 按行读取文件内容。返回一个字符串的List,文件有多少行,队列中就有多少个元素。
readBytes : 读取字节数组形式的文件内容。
这几个方法理解起来毫不费力,从文件中读取全部的文本,也只要下面一行代码便成:

    //读取文件的文本内容
val content = File(file_path).readText()

若想从图片文件中读取位图信息,按上面的函数说明,应能调用readBytes方法。该办法确实可行,因为Android的位图工厂BitmapFactory刚好提供了decodeByteArray函数,用于从字节数组中解析位图,具体代码如下所示:

    //方式一:利用字节数组读取位图
//readBytes读取字节数组形式的文件内容
val bytes = File(file_path).readBytes()
//decodeByteArray从字节数组解析图片
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)

之前提到将位图保存为图片文件时,通过输出流进行处理;那么反过来,从图片文件读取位图数据,也可通过输入流来完成。当然多亏了BitmapFactory的decodeStream方法,使得输入流解析位图能够变成现实,以下便是输入流方式读取图片的代码例子:

    //方式二:利用输入流读取位图
//inputStream获取文件的输入流对象
val fis = File(file_path).inputStream()
//decodeStream从输入流解析图片
val bitmap = BitmapFactory.decodeStream(fis)
fis.close()

前两种读取图片文件的方式,其实都包含两个步骤:先从File对象获得文件内容,再利用位图工厂解码成位图。尽管这么做也只需两行代码,还是不如读取文本的一行代码来得精炼,对于精益求精的开发者来说,此处仍然有着改善的空间。幸好位图工厂留了一手终极大招,名叫decodeFile,只要给出图片文件的完整路径,文件读取和位图解析的操作都一齐搞定了,具体代码见下:

    //方式三:直接从文件路径获取位图
//decodeFile从指定路径解析图片
val bitmap = BitmapFactory.decodeFile(file_path)

真是想不到,光光从图片读取位图数据这个小功能,就有至少三种方式,不但学到了Kotlin的文件读取API,而且温习了Android的BitmapFactory类。开发者的口味各不相同,不管个人的偏好写法是啥,以上三种方式总有一款适合你。

写文件和读文件是处理单个文件,没有太复杂的需求。倘若要求遍历某个目录下面的所有文本文件或者图片文件,那可麻烦了,因为该功能的需求点可丰富了,例如要不要到子目录和孙子目录下搜索、文件跟文件夹都要匹配还是只匹配其中之一、筛选条件的文件扩展名都有哪些?想想这些详细的功能点都觉得头大,就算好不容易把符合条件的文件都挑出来,末了还得再来一个for循环完成处理操作。如果遍历功能采用Java编码,新手绝对无法自己写出实现代码,饶是高手也要颇费一番折腾。
现在有了Kotlin就方便多了,因为Kotlin把目录遍历这个功能重新梳理了一下,归纳为FileTreeWalk文件树,通过给文件树设置各式各样的参数与条件,即可化繁为简,轻轻松松获取文件的搜索结果。文件树的使用很简单,首先调用File对象的walk方法得到FileTreeWalk实例,接着依次为该实例设置具体的条件,包括遍历深度、是否匹配文件夹、文件扩展名,以及最后的文件队列循环处理。心动不如行动,快来看看Kotlin的文件遍历是怎么实现的,下面是搜寻指定目录下面所有文本文件的示例代码:

    var fileNames: MutableList<String> = mutableListOf()
//在该目录下走一圈,得到文件目录树结构
val fileTree: FileTreeWalk = File(mPath).walk()
fileTree.maxDepth(1) //需遍历的目录层级为1,即无需检查子目录
.filter { it.isFile } //只挑选文件,不处理文件夹
.filter { it.extension == "txt" } //选择扩展名为txt的文本文件
.forEach { fileNames.add(it.name) } //循环处理符合条件的文件

注意到以上代码判断文件扩展名使用了“it.extension == "txt"”,如果符合条件的扩展名只有一种那还好办,如果符合条件的扩展名有多个又该如何是好?譬如图片文件的扩展名既可能是png,也可能是jpg,此时若用传统的或语句判断固然可行,但并不雅观,更好的办法是利用Kotlin的in条件,即判断文件的扩展名是否位于扩展名队列中,形如“it.extension in listOf("png","jpg")”这样,完整的图片文件搜索代码如下所示:

    var fileNames: MutableList<String> = mutableListOf()
//在该目录下走一圈,得到文件目录树结构
val fileTree: FileTreeWalk = File(mPath).walk()
fileTree.maxDepth(1) //需遍历的目录层级为1,即无需检查子目录
.filter { it.isFile } //只挑选文件,不处理文件夹
.filter { it.extension in listOf("png","jpg") } //选择扩展名为png和jpg的图片文件
.forEach { fileNames.add(it.name) } //循环处理符合条件的文件

见识了Kotlin强大的文件操作API,真教人耳目一新,如果你厌倦了Java的繁文缛节,不妨来Kotlin这里小试身手。

Kotlin入门(27)文件读写操作的更多相关文章

  1. Kotlin入门-文件读写操作

    转 https://blog.csdn.net/aqi00/article/details/83241762 Java的文件处理用到了io库java.io,该库虽然功能强大,但是与文件内容的交互还得通 ...

  2. PHP文件读写操作之文件写入代码

    在PHP网站开发中,存储数据通常有两种方式,一种以文本文件方式存储,比如txt文件,一种是以数据库方式存储,比如Mysql,相对于数据库存储,文件存储并没有什么优势,但是文件读写操作在基本的PHP开发 ...

  3. c语言文件读写操作总结

    C语言文件读写操作总结 C语言文件操作 一.标准文件的读写 1.文件的打开 fopen() 文件的打开操作表示将给用户指定的文件在内存分配一个FILE结构区,并将该结构的指针返回给用户程序,以后用户程 ...

  4. [转]Android - 文件读写操作 总结

     转自:http://blog.csdn.net/ztp800201/article/details/7322110 Android - 文件读写操作 总结 分类: Android2012-03-05 ...

  5. Java 字节流实现文件读写操作(InputStream-OutputStream)

    Java 字节流实现文件读写操作(InputStream-OutputStream) 备注:字节流比字符流底层,但是效率底下. 字符流地址:http://pengyan5945.iteye.com/b ...

  6. Java 字符流实现文件读写操作(FileReader-FileWriter)

    Java 字符流实现文件读写操作(FileReader-FileWriter) 备注:字符流效率高,但是没有字节流底层 字节流地址:http://pengyan5945.iteye.com/blog/ ...

  7. python(三)一个文件读写操作的小程序

    我们要实现一个文件读写操作的小程序 首先我们有一个文件 我们要以"============"为界限,每一个角色分割成一个独立的txt文件,按照分割线走的话是分成 xiaoNa_1. ...

  8. 实现动态的XML文件读写操作

    实现动态的XML文件读写操作(依然带干货) 前言 最近由于项目需求,需要读写操作XML文件,并且存储的XML文件格式会随着导入的数据不同而随时改变(当然导入的数据还是有一定约束的),这样我们要预先定义 ...

  9. ios 简单的plist文件读写操作(Document和NSUserDefaults)

    最近遇到ios上文件读写操作的有关知识,记录下来,以便以后查阅,同时分享与大家. 一,简单介绍一下常用的plist文件. 全名是:Property List,属性列表文件,它是一种用来存储串行化后的对 ...

随机推荐

  1. Elastic Search 上市了,市值翻倍,这群人财务自由了!

    国庆长假,大部分人还深浸在风花雪月之中,而就在昨天(美国时间10月5号),我们 Java 程序员所熟知的大名鼎鼎的 Elastic Search 居然在美国纽约证券交易所上市了! 当说到搜索时,大部分 ...

  2. ionic3 npm install cordova error syscall rename

    突然出现cordova 不是内部或外部命令,也不是可运行的程序或批处理文件. 可是之前cordova安装后一直用的好好的啊,后来尝试重新安装cordova 出现这个错误.也尝试重新安装了最新版本的no ...

  3. 【python小工具】我在bilibili个人资料里控制家里的电脑

    今天在52学习到的,大佬A是在网易云音乐   歌单设置  里,过程没看到,封装一个exe了,可以控制本地cmd命令\ 思路很奇特,想了一下感觉实现应该简单,就打算自己实现一下\ 两步走:网页正则和本地 ...

  4. 用dos命令导出一个文件夹里面所有文件的名字(装逼利器)

    首先,当然是在相关的文件夹打开dos命令窗口. 然后,输入如下命令:dir/b >a.txt 如果你非常了解dos命令,那么你一定会觉得这个东西简单到爆,而且我的理解和猜想都有些无知. 但如果你 ...

  5. 一览js模块化:从CommonJS到ES6

    本文由云+社区发表 模块化是指把一个复杂的系统分解到一个一个的模块. 模块化开发的优点: (1)代码复用,让我们更方便地进行代码管理.同时也便于后面代码的修改和维护. (2)一个单独的文件就是一个模块 ...

  6. RabbitMQ系列(六)你不知道的RabbitMQ集群架构全解

    前言 本文将系统的介绍一下RabbitMQ集群架构的特点.异常处理.搭建和使用中要注意的一些细节. 知识点 一.为什么使用集群? 二.集群的特点 三.集群异常处理 四.集群节点类型 五.集群搭建方法 ...

  7. DRF之项目搭建

    DRF,全称Django Restful Framework,是一个基于Django的Restful接口框架,是主要用来做API接口的,为前端提供数据的接口.在前面一片博客中,我们构建了一个vue的项 ...

  8. 利用反射跟自定义注解拼接实体对象的查询SQL

    前言 项目中虽然有ORM映射框架来帮我们拼写SQL,简化开发过程,降低开发难度.但难免会出现需要自己拼写SQL的情况,这里分享一个利用反射跟自定义注解拼接实体对象的查询SQL的方法. 代码 自定义注解 ...

  9. Linux核心命令

    Linux核心命令 strace(查看系统调用的一个过程) 例:strace cat /test.txt netstat perf top pidstat mpstat dstat vmstat sl ...

  10. [转]Ubuntu18.04下使用Docker Registry快速搭建私有镜像仓库

    本文转自:https://blog.csdn.net/BigData_Mining/article/details/88233015 1.背景 在 Docker 中,当我们执行 docker pull ...