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

相关推荐
我命由我123452 小时前
Kotlin 运算符 - == 运算符与 === 运算符
android·java·开发语言·java-ee·kotlin·android studio·android-studio
我命由我123455 小时前
Android Jetpack Compose - TopAppBar、BottomAppBar、Scaffold
android·java·java-ee·kotlin·android studio·android jetpack·android-studio
a3158238066 小时前
Android 大图显示策略优化显示(二)
android·java·开发语言·javascript·kotlin·glide·图片加载
资生算法程序员_畅想家_剑魔8 小时前
Kotlin常见技术分享-01-相对于Java 的核心优势-空安全
java·安全·kotlin
Android-Flutter1 天前
android compose LazyColumn 垂直列表滚动 使用
android·kotlin
儿歌八万首1 天前
Jetpack Compose 自定义布局解析
kotlin·compose·自定义布局
Kapaseker1 天前
初级与中级的Android面试题区别在哪里
android·kotlin
zFox1 天前
二、Kotlin高级特性以及Compose状态驱动UI
ui·kotlin·compose
PuddingSama2 天前
Gson 很好,但在Kotlin上有更合适的序列化工具「Kotlin Serialization」
android·kotlin·gson
郑梓斌2 天前
Luban 2:简洁高效的Android图片压缩库
微信·kotlin