Kotlin竞技编程中如何让readln()从文件读取以复用代码?
Kotlin竞技编程:复用readln()实现控制台/文件输入切换
你需要在竞技编程中切换控制台输入和文件输入,同时避免重复编写业务代码,之前尝试的嵌套useWith方案无法正常运行,核心问题是嵌套的with会覆盖上下文——内层PrintWriter的上下文会替换外层的BufferedReader/Scanner,导致你调用的readLine()/nextInt()找不到对应方法。
下面提供两种实用解决方案:
方案1:重定向标准输入输出
直接修改System.in和System.out,让readln()和println()默认读写文件,业务代码无需任何改动:
import java.io.File import java.io.PrintStream import java.nio.file.Files fun main() { // 保存原始控制台输入输出 val originalIn = System.`in` val originalOut = System.out try { // 重定向输入到a.in,输出到a.out System.setIn(Files.newInputStream(File("a.in").toPath())) System.setOut(PrintStream(File("a.out"))) // 业务代码和控制台版本完全一致 val (a, b) = readln()!!.split(' ').map(String::toInt) println(a + b) } finally { // 恢复控制台输入输出 System.setIn(originalIn) System.setOut(originalOut) } }
这种方式的优势是完全复用原有控制台代码,不需要额外封装,适合快速切换场景。
方案2:封装IO上下文高阶函数
通过高阶函数封装输入输出流,在函数块内提供统一的读取/打印接口,业务代码保持一致:
针对BufferedReader的版本
import java.io.BufferedReader import java.io.File import java.io.PrintWriter import java.io.Reader import java.io.Writer fun runWithIO( input: Reader = BufferedReader(System.`in`.reader()), output: Writer = PrintWriter(System.out) ) { input.use { reader -> output.use { writer -> // 定义块内专属的readln和println fun readln(): String? = (reader as BufferedReader).readLine() fun println(s: Any?) = writer.apply { write("$s\n"); flush() } // 业务代码 val (a, b) = readln()!!.split(' ').map(String::toInt) println(a + b) } } } fun main() { // 从文件读写 runWithIO( input = File("a.in").bufferedReader(), output = File("a.out").printWriter() ) // 默认使用控制台读写 runWithIO() }
针对Scanner的版本
如果习惯用Scanner处理输入,可以封装对应版本:
import java.io.File import java.io.PrintWriter import java.util.Scanner fun runWithScanner( input: Scanner = Scanner(System.`in`), output: PrintWriter = PrintWriter(System.out) ) { input.use { scanner -> output.use { writer -> // 定义块内专属的读取和打印方法 fun nextInt(): Int = scanner.nextInt() fun println(s: Any?) = writer.apply { write("$s\n"); flush() } // 业务代码 val a = nextInt() val b = nextInt() println(a + b) } } } fun main() { // 从文件读写 runWithScanner( input = Scanner(File("b.in")), output = PrintWriter(File("b.out")) ) }
这种方式的优势是隔离了IO实现,业务代码完全与输入输出源无关,适合需要频繁切换场景。
内容的提问来源于stack exchange,提问作者Quentin M
相关产品推荐
相关产品推荐

