在实际开发过程中,我们经常会遇到需要处理大文本文件的场景,比如日志文件、小说文本等。当文件过大时,直接打开可能会导致程序卡顿甚至崩溃。为了解决这个问题,我们可以将大文本文件按指定大小拆分成多个小文件,方便处理和查看。
本文介绍如何使用 Kotlin 实现文本文件拆分的功能,并提供完整代码示例。
功能需求
- 读取一个大文本文件。
- 按照指定的字符数(如 190000 字符)拆分文件。
- 处理不同的文件编码(支持 UTF-8、GBK、UTF-16)。
- 将拆分后的文件存放到一个与原文件同名的文件夹中。
- 保留原始文件的扩展名,文件名格式为
文件名_1.txt
,文件名_2.txt
。
代码实现
我们编写一个 splitTxtFile
函数来实现该功能,并确保能够处理不同的编码。
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? = nullfor (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.nameWithoutExtensionval 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 // 每个文件10MBsplitTxtFile(filePath, maxChars)
}
代码解析
1. 处理文件编码
不同的文本文件可能使用不同的编码格式,如 UTF-8、GBK、UTF-16。为了避免编码错误,我们提供了一个编码列表,代码会尝试使用不同编码打开文件,直到成功读取。
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. 创建存放分割文件的目录
我们获取原始文件所在的目录,并创建一个与原文件同名的文件夹,用于存放拆分后的文件。
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
限制时将当前内容写入新的文件。
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
,依此类推。
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
进行拆分。
fun main() {val filePath = "C:/abc.txt"val maxChars = 10240000 // 每个文件10MBsplitTxtFile(filePath, maxChars)
}
运行后,程序会在 C:/abc/
目录下生成多个拆分后的文件。
总结
本文介绍了如何使用 Kotlin 拆分大文本文件,支持自动检测编码,并将拆分后的文件存放在指定目录。代码采用逐行读取方式,避免内存溢出,适用于大文件处理场景。希望对你有所帮助!