【修改】 C语言判分后输出中文变乱码

This commit is contained in:
dlaren
2025-08-24 19:21:29 +08:00
parent 4bf3e03bde
commit b8ed974289

View File

@@ -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<String> 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<String> 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 文件路径