在实际开发过程中,我们经常会遇到需要处理大文本文件的场景,比如日志文件、小说文本等。当文件过大时,直接打开可能会导致程序卡顿甚至崩溃。为了解决这个问题,我们可以将大文本文件按指定大小拆分成多个小文件,方便处理和查看。
本文介绍如何使用 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? = 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。为了避免编码错误,我们提供了一个编码列表,代码会尝试使用不同编码打开文件,直到成功读取。
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 // 每个文件10MB
splitTxtFile(filePath, maxChars)
}
运行后,程序会在 C:/abc/
目录下生成多个拆分后的文件。
总结
本文介绍了如何使用 Kotlin 拆分大文本文件,支持自动检测编码,并将拆分后的文件存放在指定目录。代码采用逐行读取方式,避免内存溢出,适用于大文件处理场景。希望对你有所帮助!