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. python(leetcode)-283移动零

    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数组上操作, ...

  2. [java]创建一个默认TreeMap() key为什么不能为null

    本文版权归 远方的风lyh和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 先看一下 TreeMap 的 put(K key, V value) public TreeMap() ...

  3. [NewLife.XCode]高级查询(化繁为简、分页提升性能)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  4. 【K8S】client-go、python-k8sclient开发K8S

    0x01 client-go 1.简介 Client-go是kubernetes官方发布的调用K8S API的golang语言包,可以用来开发K8S的管理服务.监控服务,配合前端展示,就可以开发出一款 ...

  5. python干掉pycache

    当第一次运行 python 脚本时,解释器会将 *.py 脚本进行编译并保存到 __pycache__ 目录 下次执行脚本时,若解释器发现你的 *.py 脚本没有变更,便会跳过编译一步,直接运行保存在 ...

  6. Mysql加锁过程详解(1)-基本知识

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  7. Perl文件测试操作和stat函数

    在shell中通过test命令或者中括号[]可以进行文件测试以及其它类型的测试,例如判断文件是否存在,比较操作是否为真等等.perl作为更强大的文本处理语言,它也有文件测试类表达式,而且和shell的 ...

  8. HTTP状态码分类

    前言: 我们经常使用浏览器发出http请求,那么对于请求返回的状态,对于开发人员来讲,我们必须要明白其所代表的含义,如: 常见状态吗:400(请求无效),401(需要权限),500(服务器错误), 今 ...

  9. 一个简单的Code First建立

    1]从VS中建立一个mvc程序 记得添加NuGet包 然后在web.config中添加链接数据库的语句 <connectionStrings> <add name="Ent ...

  10. Postgresql ODBC驱动,用sqlserver添加dblink跨库访问postgresql数据库

    在同样是SQLserver数据库跨库访问时,只需要以下方法 declare @rowcount int set @rowcount =(select COUNT(*) from sys.servers ...