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

相关推荐
Kapaseker12 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
Kapaseker2 天前
一杯美式搞定 Kotlin 空安全
android·kotlin
FunnySaltyFish2 天前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
Kapaseker2 天前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker3 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
A0微声z5 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton6 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream6 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam6 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker7 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin