Kotlin - 文件类 File

本文介绍了Kotlin中如何使用FileTreeWalk进行文件遍历,包括walk、walkBottomUp、walkTopDown方法,以及文件名处理、流读写操作、文件复制、删除和Java流对象的使用。重点讲解了文件过滤、复制、删除的技巧和流处理的最佳实践。

一、概念

File能新建、删除、重命名文件和目录,但不能访问文件内容,需要作为参数传递给IO流的构造。

二、普通使用

2.1 创建

构造public File(String pathname)
public File(String parent, String child)
public File(File parent, String child)
public File(URI uri)
//拿到外置缓存路径后,拼接文件名
val file = File(externalCacheDir?.absolutePath + "/MyFile.txt")
//拿到外置缓存路径后,拼接文件夹名
val directory = File(externalCacheDir?.absolutePath + "/MyDirectory")

2.2 获取信息

文件名name

public String getName()

文件名

nameWithoutExtension

public val File.nameWithoutExtension: String

文件名,不包含后缀

extension

public val File.extension: String

文件的后缀格式,不包含“.”,例如 mp3。

absoluteFile

public File getAbsoluteFile()

绝对路径文件名

路径path

public String getPath()

路径。

absolutePath

public String getAbsolutePath()

绝对路径。

isAbsolute

public boolean isAbsolute()

是否是绝对路径。

parent

public String getParent()

父路径,String形式。

parentFile

public File getParentFile()

父路径,File形式。

判断exists()

public boolean exists()

是否已存在。

isDirectory

public boolean isDirectory()

是否是目录。

canExecute()

public boolean canExecute()

是否可执行。

canRead()

public boolean canRead()

是否可读取。

canWrite()

public boolean canWrite()

是否可写入。

其它length()

public long length()

文件大小,单位字节,无法返回文件夹大小。

lastModified

public long lastModified()

表示文件最近修改时间的 long 型数值(从纪元时间 1970年1月1日 00:00:00 GMT 起的毫秒数)。若文件不存在或发生 I/O 错误,则返回 0L

val file = File(externalCacheDir?.absolutePath + "/MyFile.txt")
println("文件名:${file.name}")     //打印:MyFile.txt
println("绝对文件名:${file.absoluteFile}")   //打印:/storage/emulated/0/Android/data/com.jomurphys.dc/cache/MyFile.txt
println("绝对路径名:${file.absolutePath}")   //打印:/storage/emulated/0/Android/data/com.jomurphys.dc/cache/MyFile.txt
println("路径:${file.path}")      //打印:/storage/emulated/0/Android/data/com.jomurphys.dc/cache/MyFile.txt
println("父目录:${file.parent}")   //打印:/storage/emulated/0/Android/data/com.jomurphys.dc/cache
val newFile = File(externalCacheDir?.absolutePath + "/NewName.txt")
val b = file.renameTo(newFile)
println("重命名是否成功:$b,新名称:${file.name}")   //打印:false
println("是否存在:${file.exists()}")     //打印:false
println("能否执行:${file.canExecute()}")     //打印:false
println("可读吗:${file.canRead()}")     //打印:dalse
println("可写吗:${file.canWrite()}")     //打印:false
println("是目录吗:${file.isDirectory}")     //打印:false
println("上一次修改:${file.lastModified()}")     //打印:0
println("长度:${file.length()}")     //打印:0

2.3 文件夹操作

mkdirs()public boolean mkdirs()
mkdirs()

public boolean mkdirs()

创建文件夹,上级路径不存在会一并创建。

list()

public String[] list()

获取路径中所有文件和文件夹。

listFiles()

public File[] listFiles()

获取路径中所有文件。

val directory = File(externalCacheDir?.absolutePath + "/Dir111/Dir222")
//创建文件夹,上级路径不存在会一并创建
directory.mkdirs()
//获取文件夹中所有文件和文件夹
val list = directory.list()
for (i in list) { println(i) }  //打印的是文件名或文件夹名
//获取文件夹中的所有文件
val files = directory.listFiles()
for (file in files) { println(file) }   //打印出来的是文件名

三、扩展方法

上面的都是 Java 提供的方法,Kotlin 扩展了一些方法和属性更方便操作。

3.1 获取信息

extension()

public val File.extension: String

文件后缀名,不包括那个点。

nameWithoutExtension()

public val File.nameWithoutExtension: String

文件名,不包括后缀。

3.2 遍历

Kotlin把目录遍历这个功能重新梳理了一下,归纳为FileTreeWalk文件树。首先调用File对象的walk方法得到FileTreeWalk实例,接着依次为该实例设置具体的条件,包括遍历深度、是否匹配文件夹、文件扩展名,以及最后的文件队列循环处理。

walk()自上而下,深度优先,遍历整个文件夹。
walkBottomUp()自下而上的顺序遍历文件目录和内容。
walkTopDown()自上而下的顺序遍历文件目录和内容。
//遍历文件
file.parentFile //获取上级目录
    .walk() //先访问文件夹,再访问里面的内容
    .maxDepth(1)//需遍历的目录层级为1,即无需检查子目录
    .filter { it.isFile } //只挑选文件,不处理文件夹
    .filter { it.extension in listOf("png","jpg") } //选择扩展名为png和jpg的图片文件
//        .filter { it.extension.equals("txt", true) }
    .forEach(::println)//循环处理符合条件的文件

//文件拷贝
file.copyTo(File(file.parent, "copy.txt"), true)
//文件夹拷贝
//target:新地址
//overwrite:是否覆盖
//onError:失败的回调
file.parentFile.copyRecursively(
    File(file.parentFile.parentFile.parent, "copyRecursively"),
    true
)

3.3 简化读取

字符readText()

File.readText(charset: Charset = Charsets.UTF_8): String

以 String 形式获取此文件的全部内容,默认编码UTF-8,不要在大文件上使用此方法,上限2G。

readLines()

public fun File.readLines(charset: Charset = Charsets.UTF_8): List<String>

以 List<String> 形式获取此文件的全部内容,一行内容是一个元素,只能是文本。不要在大文件上使用此方法。

useLines()

public inline fun <T> File.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence<String>) -> T): T

拿到所有行的序列,并调用action。

forEachLine()

public fun File.forEachLine(charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit

按行读取文件并为每行调用action,适用于大文件。

文件readBytes()

public fun File.readBytes(): ByteArray

以 ByteArray 的形式获取此文件的全部内容,不要在大文件上使用此方法,上限2G。

forEachBlock()

public fun File.forEachBlock(action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit 
public fun File.forEachBlock(blockSize: Int, action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit

按字节块读取文件并为每个读取的块调用action,字节块默认为4096,最小可为512。适用于大文件。

3.4 简化写入

字符writeText()

public fun File.writeText(text: String, charset: Charset = Charsets.UTF_8): Unit

写入字符串,已有同名文件会覆盖。

appendText()

public fun File.appendText(text: String, charset: Charset = Charsets.UTF_8): Unit

追加字符串到文件末尾。

文件writeBytes()

public fun File.appendBytes(array: ByteArray): Unit

写入字节数组,已有同名文件会覆盖。

appendBytes()

public fun File.writeBytes(array: ByteArray): Unit

追加字节数组到文件末尾。

3.5 拷贝

copyTo()复制文件或者文件夹,并且会创建target所需的各个父级文件夹(如果缺少)。overwrite为true时,target可被覆盖,不为true并且当target存在时,返回false,复制失败。overwrite为true并且target是一个文件夹时,只有当文件夹为空时才会被替换。源文件如果是文件夹,则只会创建目标文件夹,不会复制文件夹中的文件。该操作不会保留复制的文件属性,例如创建/修改日期、权限等。
copyRecursively()递归复制文件或者文件夹,并且会创建target所需的各个父级文件夹(如果缺少)。如果源文件是文件夹,将复制文件夹中的所有内容。该操作不会保留复制的文件属性,例如创建/修改日期、权限等。默认自带的错误处理器会将错误抛出,可以传入一个Lambda用来处理异常。复制文件夹失败时,可能已经复制了一部分。

3.6 删除

deleteRecursively()

public fun File.deleteRecursively(): Boolean

递归删除文件或者文件夹,删除文件夹失败时,可能已经删除了一部分。

3.7 IO流

inputStream()

outputStream()

public inline fun File.inputStream(): FileInputStream
public inline fun File.outputStream(): FileOutputStream

reader()

writer()

public inline fun File.reader(charset: Charset = Charsets.UTF_8): InputStreamReader

返回一个InputStreamReader以读取此文件的内容。

public inline fun File.writer(charset: Charset = Charsets.UTF_8): OutputStreamWriter

返回一个OutputStreamWriter用于写入此文件。

bufferedReader()

bufferedWriter()

public inline fun File.bufferedReader(charset: Charset = Charsets.UTF_8, bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedReader

返回一个BufferedReader用于读取此文件的内容,默认大小8*1024。

public inline fun File.bufferedWriter(charset: Charset = Charsets.UTF_8, bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedWriter

返回一个BufferedWriter用于写入此文件。

printWrite()public inline fun File.printWriter(charset: Charset = Charsets.UTF_8): PrintWriter
val file = File("m:\\demo.txt")

fun read() {
    println(file.readText())    //段落之间有换行
    file.readLines().forEach(::println)
    file.forEachLine { println(it) }
    file.forEachBlock { buffer, bytesRead -> print(buffer.decodeToString()) }
    file.bufferedReader().use { it.readLines().forEach(::println) }
    file.inputStream().use {
        //一个个读取太慢
//        var num: Int
//        while (it.read().also { num = it } != -1) {
//            print(num.toChar())
//        }
//    }
        val arr = ByteArray(1024)
        var num: Int
        while (it.read(arr).also { num = it } != -1) {
            print(arr.decodeToString(0, num))  //使用num而不是arr.size是因为最后一次读取不一定能读满,不然后面全时空格
//            print(String(arr, 0, num))    //效果同上
        }
    }

}

fun write() {
    //覆盖
    file.writeBytes("writeBytes\n".toByteArray())
    file.writeText("writeText\n")
    file.outputStream().use { it.write("outputStream\n".toByteArray()) }
    file.printWriter().use { it.println("printlnWriter") }
    file.bufferedWriter().use { it.write("bufferedWriter") }
    //追加
    file.appendBytes("appendBytes".toByteArray())
    file.appendText("appendText")

}
### Kotlin 编译器嵌入式组件的下载与使用 Kotlin 编译器嵌入式组件(Kotlin Compiler Embeddable Component)是一种允许开发者将 Kotlin 编译器集成到自身应用程序中的工具。它通常用于需要动态编译或运行 Kotlin 代码的场景,例如构建工具、IDE 插件或脚本执行环境。 #### 下载 Kotlin 编译器嵌入式组件 Kotlin 编译器嵌入式组件可以通过 Maven Central 或其他依赖管理工具进行下载。以下是通过 Maven 和 Gradle 添加依赖的示例: - **Maven**: ```xml <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-compiler-embeddable</artifactId> <version>1.8.20</version> <!-- 替换为所需版本 --> </dependency> ``` - **Gradle**: ```groovy implementation 'org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.20' // 替换为所需版本 ``` 确保选择适合项目需求的 Kotlin 版本[^2]。 #### 使用 Kotlin 编译器嵌入式组件 Kotlin 编译器嵌入式组件提供了 `KotlinCompiler` 类,允许在 Java 或 Kotlin 应用程序中调用 Kotlin 编译器的功能。以下是一个简单的代码示例,展示如何使用嵌入式编译器来编译 Kotlin 源代码: ```java import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; import org.jetbrains.kotlin.cli.common.messages.MessageCollector; import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler; import org.jetbrains.kotlin.config.Services; import org.jetbrains.kotlin.compilerRunner.CompilerRunnerConstants; import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner; import java.io.File; import java.util.Collections; public class KotlinCompilerExample { public static void main(String[] args) { MessageCollector messageCollector = MessageCollector.NONE; Services services = Services.EMPTY.with(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector); String[] compilerArgs = new String[]{ "-classpath", "path/to/your/classpath", "-d", "output/directory", "path/to/source/file.kt" }; K2JVMCompiler compiler = new K2JVMCompiler(); boolean result = compiler.exec(messageCollector, services, compilerArgs); if (result) { System.out.println("Compilation succeeded!"); } else { System.out.println("Compilation failed."); } } } ``` 上述代码展示了如何通过 `K2JVMCompiler` 类编译 Kotlin 文件,并设置编译参数[^3]。 #### GraalVM 与 Kotlin 的结合 GraalVM 提供了增强的性能优化能力,适用于基于 JVM 的语言和应用。尽管 GraalVM 主要针对 Java 应用进行了优化,但也可以与 Kotlin 结合使用。通过 GraalVM 的动态编译器,可以进一步提升 Kotlin 应用的运行效率和启动速度[^1]。 #### 注意事项 1. 确保使用的 Kotlin 编译器版本与项目中其他 Kotlin 组件版本一致,以避免兼容性问题。 2. 嵌入式编译器可能增加应用程序的内存占用和启动时间,需根据实际需求权衡使用。 3. 如果计划在生产环境中使用嵌入式编译器,建议对目标平台进行充分测试[^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值