使用 Kotlin 拆分大文本文件

在实际开发过程中,我们经常会遇到需要处理大文本文件的场景,比如日志文件、小说文本等。当文件过大时,直接打开可能会导致程序卡顿甚至崩溃。为了解决这个问题,我们可以将大文本文件按指定大小拆分成多个小文件,方便处理和查看。

本文介绍如何使用 Kotlin 实现文本文件拆分的功能,并提供完整代码示例。

功能需求

  • 读取一个大文本文件。
  • 按照指定的字符数(如 190000 字符)拆分文件。
  • 处理不同的文件编码(支持 UTF-8、GBK、UTF-16)。
  • 将拆分后的文件存放到一个与原文件同名的文件夹中。
  • 保留原始文件的扩展名,文件名格式为 文件名_1.txt文件名_2.txt

代码实现

我们编写一个 splitTxtFile 函数来实现该功能,并确保能够处理不同的编码。

kotlin 复制代码
import java.io.*
import java.nio.charset.Charset

/**
 * 按指定字符数拆分大文本文件,并存放到与原文件同名的文件夹中。
 * 支持 UTF-8 / GBK / UTF-16 编码自动切换,防止编码不兼容问题。
 *
 * @param filePath 要拆分的文件路径
 * @param maxChars 每个分割文件的最大字符数
 * @param encodingList 尝试使用的字符编码列表
 */
fun splitTxtFile(filePath: String, maxChars: Int, encodingList: List<String> = listOf("UTF-8", "GBK", "UTF-16")) {
    val file = File(filePath)
    if (!file.exists()) {
        println("文件不存在,请检查路径")
        return
    }

    // 尝试不同编码方式打开文件,防止编码错误
    var reader: BufferedReader? = null
    for (encoding in encodingList) {
        try {
            reader = file.bufferedReader(Charset.forName(encoding))
            break  // 成功读取则跳出循环
        } catch (e: UnsupportedEncodingException) {
            continue
        } catch (e: IOException) {
            continue
        }
    }

    if (reader == null) {
        println("无法解析文件编码")
        return
    }

    // 获取文件所在目录、文件名(无后缀)和扩展名
    val parentDir = file.parent ?: "."
    val fileName = file.nameWithoutExtension
    val fileExt = file.extension

    // 创建新文件夹存放分割后的文件
    val newFolder = File(parentDir, fileName)
    if (!newFolder.exists()) newFolder.mkdirs()

    var partContent = StringBuilder()
    var partNum = 1

    // 逐行读取文件内容,防止一次性读取导致内存溢出
    reader.useLines { lines ->
        lines.forEach { line ->
            if (partContent.length + line.length > maxChars) {
                savePartFile(newFolder, fileName, fileExt, partNum, partContent.toString())
                partContent.clear()
                partNum++
            }
            partContent.append(line).append("\n")
        }
    }

    // 处理最后一部分
    if (partContent.isNotEmpty()) {
        savePartFile(newFolder, fileName, fileExt, partNum, partContent.toString())
    }

    println("文件拆分完成,共生成 $partNum 个文件。")
}

/**
 * 保存拆分后的文件到新目录
 * @param folder 存放文件的文件夹
 * @param baseName 原始文件名(无扩展名)
 * @param ext 原始文件扩展名
 * @param partNum 拆分的文件序号
 * @param content 文件内容
 */
fun savePartFile(folder: File, baseName: String, ext: String, partNum: Int, content: String) {
    val newFile = File(folder, "${baseName}_$partNum.$ext")
    newFile.writeText(content, Charsets.UTF_8)
}

fun main() {
    val filePath = "C:/abc.txt"
    val maxChars = 10240000 // 每个文件10MB
    splitTxtFile(filePath, maxChars)
}

代码解析

1. 处理文件编码

不同的文本文件可能使用不同的编码格式,如 UTF-8、GBK、UTF-16。为了避免编码错误,我们提供了一个编码列表,代码会尝试使用不同编码打开文件,直到成功读取。

kotlin 复制代码
var reader: BufferedReader? = null
for (encoding in encodingList) {
    try {
        reader = file.bufferedReader(Charset.forName(encoding))
        break
    } catch (e: UnsupportedEncodingException) {
        continue
    } catch (e: IOException) {
        continue
    }
}

2. 创建存放分割文件的目录

我们获取原始文件所在的目录,并创建一个与原文件同名的文件夹,用于存放拆分后的文件。

kotlin 复制代码
val parentDir = file.parent ?: "."
val fileName = file.nameWithoutExtension
val fileExt = file.extension
val newFolder = File(parentDir, fileName)
if (!newFolder.exists()) newFolder.mkdirs()

3. 按指定大小拆分文件

为了避免一次性读取整个文件导致内存溢出,我们使用 useLines 逐行读取文件内容,并在达到 maxChars 限制时将当前内容写入新的文件。

kotlin 复制代码
reader.useLines { lines ->
    lines.forEach { line ->
        if (partContent.length + line.length > maxChars) {
            savePartFile(newFolder, fileName, fileExt, partNum, partContent.toString())
            partContent.clear()
            partNum++
        }
        partContent.append(line).append("\n")
    }
}

4. 保存拆分后的文件

拆分后的内容会存放在新建的文件夹中,文件名格式为 文件名_1.txt文件名_2.txt,依此类推。

kotlin 复制代码
fun savePartFile(folder: File, baseName: String, ext: String, partNum: Int, content: String) {
    val newFile = File(folder, "${baseName}_$partNum.$ext")
    newFile.writeText(content, Charsets.UTF_8)
}

运行示例

假设 C:/abc.txt 是一个大文本文件,我们可以调用 splitTxtFile 进行拆分。

kotlin 复制代码
fun main() {
    val filePath = "C:/abc.txt"
    val maxChars = 10240000 // 每个文件10MB
    splitTxtFile(filePath, maxChars)
}

运行后,程序会在 C:/abc/ 目录下生成多个拆分后的文件。

总结

本文介绍了如何使用 Kotlin 拆分大文本文件,支持自动检测编码,并将拆分后的文件存放在指定目录。代码采用逐行读取方式,避免内存溢出,适用于大文件处理场景。希望对你有所帮助!

相关推荐
疏狂难除15 小时前
JetBrains IDE插件开发教程(五)——File Header
ide·kotlin
Kapaseker1 天前
Android CLI 完全指南
android·kotlin
Coffeeee2 天前
Android功耗优化,哪些代码会让你的机子发热又耗电
android·架构·kotlin
Android打工仔2 天前
Kotlin 编译器是如何把 suspend 函数变成状态机的?
kotlin
Android打工仔2 天前
一个 suspend 函数,为什么会变成一个普通函数?
kotlin
苦瓜花3 天前
【Kotlin】初入门
android·开发语言·kotlin
Kapaseker3 天前
Rust 是如何处理异常的
rust·kotlin
冬日砥砺前行3 天前
Kotlin 协程:几个曾经被我误解的点
kotlin
plainGeekDev5 天前
libs 目录 → Gradle 依赖管理
android·java·kotlin
监督者修5 天前
从零构建 GIS 数据引擎:方案驱动架构的设计与实践
android·架构·kotlin