diff --git a/src/main/java/com/example/exam/exam/utils/c/JudgementCUtils.java b/src/main/java/com/example/exam/exam/utils/c/JudgementCUtils.java index e7a8562..d7c357a 100644 --- a/src/main/java/com/example/exam/exam/utils/c/JudgementCUtils.java +++ b/src/main/java/com/example/exam/exam/utils/c/JudgementCUtils.java @@ -120,18 +120,22 @@ public class JudgementCUtils } public static String run_codes(String pathC, String code, String input, String standard, String text) { try { - boolean hasInput = code.contains("scanf") || code.contains("fgets") || code.contains("getchar"); + boolean hasInput = code != null && (code.contains("scanf") || code.contains("fgets") || code.contains("getchar")); File workDir = new File(pathC); if (!workDir.exists()) workDir.mkdirs(); boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win"); + java.nio.charset.Charset charset = pickCharset(text, isWindows); + String programC = new File(workDir, "program.c").getAbsolutePath(); String programOut = new File(workDir, isWindows ? "program.exe" : "program.out").getAbsolutePath(); - // 写入 C 源码 - try (FileWriter writer = new FileWriter(programC)) { - writer.write(code); + // 写入 C 源码(按指定字符集) + try (java.io.OutputStream os = new java.io.FileOutputStream(programC); + java.io.OutputStreamWriter writer = new java.io.OutputStreamWriter(os, charset)) { + writer.write(code == null ? "" : code); + writer.flush(); } // jar 所在目录 @@ -149,21 +153,15 @@ public class JudgementCUtils } // 编译命令 - ProcessBuilder compileBuilder; - if (stdFlag == null) { - compileBuilder = new ProcessBuilder(tccExe.getAbsolutePath(), programC, "-o", programOut); - } else { - compileBuilder = new ProcessBuilder(tccExe.getAbsolutePath(), stdFlag, programC, "-o", programOut); - } + ProcessBuilder compileBuilder = (stdFlag == null) + ? new ProcessBuilder(tccExe.getAbsolutePath(), programC, "-o", programOut) + : new ProcessBuilder(tccExe.getAbsolutePath(), stdFlag, programC, "-o", programOut); + compileBuilder.directory(workDir); compileBuilder.redirectErrorStream(true); Process compileProcess = compileBuilder.start(); - StringBuilder compileOutput = new StringBuilder(); - try (BufferedReader br = new BufferedReader(new InputStreamReader(compileProcess.getInputStream(), StandardCharsets.UTF_8))) { - String line; - while ((line = br.readLine()) != null) compileOutput.append(line).append("\n"); - } + String compileOutput = readAll(compileProcess.getInputStream(), charset); int compileResult = compileProcess.waitFor(); if (compileResult != 0 || !new File(programOut).exists()) { return "❌ 编译失败,输出:\n" + compileOutput; @@ -176,29 +174,25 @@ public class JudgementCUtils Process runProcess = runBuilder.start(); if (hasInput && input != null) { - try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(runProcess.getOutputStream()))) { + try (java.io.OutputStream os = runProcess.getOutputStream(); + java.io.OutputStreamWriter osw = new java.io.OutputStreamWriter(os, charset); + java.io.BufferedWriter bw = new java.io.BufferedWriter(osw)) { bw.write(input); bw.newLine(); bw.flush(); } + } else { + // 关闭输入流,避免某些程序等待 STDIN + try { runProcess.getOutputStream().close(); } catch (Exception ignore) {} } - ExecutorService executor = Executors.newSingleThreadExecutor(); - Future future = executor.submit(() -> { - StringBuilder output = new StringBuilder(); - // 运行过程读取输出 - try (BufferedReader br = new BufferedReader( - new InputStreamReader(runProcess.getInputStream(), StandardCharsets.UTF_8))) { - String line; - while ((line = br.readLine()) != null) output.append(line).append("\n"); - } - return output.toString(); - }); + java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newSingleThreadExecutor(); + java.util.concurrent.Future future = executor.submit(() -> readAll(runProcess.getInputStream(), charset)); String output; try { - output = future.get(5, TimeUnit.SECONDS); - } catch (TimeoutException e) { + output = future.get(5, java.util.concurrent.TimeUnit.SECONDS); + } catch (java.util.concurrent.TimeoutException e) { runProcess.destroyForcibly(); future.cancel(true); output = "⏰ 程序运行超时(超过 5 秒)"; @@ -213,6 +207,31 @@ public class JudgementCUtils return "运行 C 代码时出错:" + ex.getMessage(); } } + + private static java.nio.charset.Charset pickCharset(String text, boolean isWindows) { + if (text != null && !text.isBlank()) { + try { + return java.nio.charset.Charset.forName(text.trim()); + } catch (Exception ignore) { + // ignore and fallback + } + } + // 常见场景:Windows 中文环境默认 GBK;其他系统默认 UTF-8 + return isWindows ? java.nio.charset.Charset.forName("GBK") : java.nio.charset.StandardCharsets.UTF_8; + } + + private static String readAll(java.io.InputStream is, java.nio.charset.Charset cs) throws java.io.IOException { + try (java.io.InputStream in = is; + java.io.InputStreamReader isr = new java.io.InputStreamReader(in, cs); + java.io.BufferedReader br = new java.io.BufferedReader(isr)) { + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + sb.append(line).append('\n'); + } + return sb.toString(); + } + } /** * 读取文件代码 * @param filePath 文件路径