Kotlin读取含0x0d分隔符的大二进制文件的惯用方法
嘿,我来帮你把这段代码改成更符合Kotlin惯用风格的写法~先看看原代码的几个可以优化的点:手动管理流关闭容易出问题、while循环的写法比较生硬,还有没处理文件末尾无分隔符的情况。下面给你两种优化方案:
方案一:用use+forEachByte(最直观易读)
fun main(args: Array<String>) { File(args[0]).inputStream().buffered().use { bis -> val buffer = mutableListOf<Int>() bis.forEachByte { byte -> buffer.add(byte) if (byte == 0x0d) { process(buffer) buffer.clear() } true // 返回true表示继续读取下一个字节 } // 处理最后一段没有以0x0d结尾的内容 if (buffer.isNotEmpty()) { process(buffer) } } }
这里的关键改进:
- 用
use函数包裹流操作,Kotlin会自动帮你关闭流,不管有没有异常,彻底告别手动close()的麻烦,这是IO资源管理的标准做法。 - 用
forEachByte扩展函数替代手动while循环,代码更简洁,逻辑更清晰。这个函数会逐个读取字节直到流结束,你只需要在lambda里处理每个字节就行。 - 补上了原代码缺失的逻辑:如果文件最后没有以
0x0d结尾,这段代码会处理剩下的缓冲区内容,避免数据丢失。
方案二:函数式风格的分块处理
如果你更喜欢函数式的写法,可以用generateSequence+fold来实现:
fun main(args: Array<String>) { File(args[0]).inputStream().buffered().use { bis -> generateSequence { bis.read() } .takeWhile { it != -1 } // 直到读取到流结束标记-1 .fold(mutableListOf<Int>()) { buffer, byte -> buffer.apply { add(byte) if (byte == 0x0d) { process(toList()) // 传一个副本,避免后续clear影响process的处理 clear() } } }.let { remainingBuffer -> if (remainingBuffer.isNotEmpty()) { process(remainingBuffer) } } } }
这种写法把字节流转换成序列,用fold来维护缓冲区状态,全程用函数式操作串联逻辑,适合喜欢函数式编程风格的场景。
两种方案都比原代码更符合Kotlin的惯用风格,其中方案一的可读性更高,更推荐日常使用~
内容的提问来源于stack exchange,提问作者James Allman
相关产品推荐
相关产品推荐

