Fix #1148: Specify console encoding explicitly

This commit is contained in:
Glavo
2021-12-13 14:32:11 +08:00
committed by Yuhui Huang
parent fbf7ff6ebd
commit aa5e3e9697
2 changed files with 24 additions and 6 deletions

View File

@@ -50,8 +50,10 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.*; import java.util.*;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.logging.Level;
import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Lang.mapOf;
import static org.jackhuang.hmcl.util.Logging.LOG;
import static org.jackhuang.hmcl.util.Pair.pair; import static org.jackhuang.hmcl.util.Pair.pair;
/** /**
@@ -116,6 +118,19 @@ public class DefaultLauncher extends Launcher {
res.addAllWithoutParsing(options.getJavaArguments()); res.addAllWithoutParsing(options.getJavaArguments());
Charset encoding = OperatingSystem.NATIVE_CHARSET;
// After Java 17, file.encoding does not affect console encoding
if (options.getJava().getParsedVersion() <= JavaVersion.JAVA_17) {
try {
String fileEncoding = res.addDefault("-Dfile.encoding=", encoding.name());
if (fileEncoding != null)
encoding = Charset.forName(fileEncoding.substring("-Dfile.encoding=".length()));
} catch (Throwable ex) {
LOG.log(Level.WARNING, "Bad file encoding", ex);
}
}
// JVM Args // JVM Args
if (!options.isNoGeneratedJVMArgs()) { if (!options.isNoGeneratedJVMArgs()) {
appendJvmArgs(res); appendJvmArgs(res);
@@ -281,7 +296,7 @@ public class DefaultLauncher extends Launcher {
res.addAllWithoutParsing(Arguments.parseStringArguments(options.getGameArguments(), configuration)); res.addAllWithoutParsing(Arguments.parseStringArguments(options.getGameArguments(), configuration));
res.removeIf(it -> getForbiddens().containsKey(it) && getForbiddens().get(it).get()); res.removeIf(it -> getForbiddens().containsKey(it) && getForbiddens().get(it).get());
return new Command(res, tempNativeFolder); return new Command(res, tempNativeFolder, encoding);
} }
public Map<String, Boolean> getFeatures() { public Map<String, Boolean> getFeatures() {
@@ -469,7 +484,7 @@ public class DefaultLauncher extends Launcher {
ManagedProcess p = new ManagedProcess(process, rawCommandLine, classpath); ManagedProcess p = new ManagedProcess(process, rawCommandLine, classpath);
if (listener != null) if (listener != null)
startMonitors(p, listener, daemon); startMonitors(p, listener, command.encoding, daemon);
return p; return p;
} }
@@ -634,17 +649,17 @@ public class DefaultLauncher extends Launcher {
throw new ExecutionPolicyLimitException(); throw new ExecutionPolicyLimitException();
} }
private void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, boolean isDaemon) { private void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, Charset encoding, boolean isDaemon) {
processListener.setProcess(managedProcess); processListener.setProcess(managedProcess);
Thread stdout = Lang.thread(new StreamPump(managedProcess.getProcess().getInputStream(), it -> { Thread stdout = Lang.thread(new StreamPump(managedProcess.getProcess().getInputStream(), it -> {
processListener.onLog(it, Optional.ofNullable(Log4jLevel.guessLevel(it)).orElse(Log4jLevel.INFO)); processListener.onLog(it, Optional.ofNullable(Log4jLevel.guessLevel(it)).orElse(Log4jLevel.INFO));
managedProcess.addLine(it); managedProcess.addLine(it);
}, OperatingSystem.NATIVE_CHARSET), "stdout-pump", isDaemon); }, encoding), "stdout-pump", isDaemon);
managedProcess.addRelatedThread(stdout); managedProcess.addRelatedThread(stdout);
Thread stderr = Lang.thread(new StreamPump(managedProcess.getProcess().getErrorStream(), it -> { Thread stderr = Lang.thread(new StreamPump(managedProcess.getProcess().getErrorStream(), it -> {
processListener.onLog(it, Log4jLevel.ERROR); processListener.onLog(it, Log4jLevel.ERROR);
managedProcess.addLine(it); managedProcess.addLine(it);
}, OperatingSystem.NATIVE_CHARSET), "stderr-pump", isDaemon); }, encoding), "stderr-pump", isDaemon);
managedProcess.addRelatedThread(stderr); managedProcess.addRelatedThread(stderr);
managedProcess.addRelatedThread(Lang.thread(new ExitWaiter(managedProcess, Arrays.asList(stdout, stderr), processListener::onExit), "exit-waiter", isDaemon)); managedProcess.addRelatedThread(Lang.thread(new ExitWaiter(managedProcess, Arrays.asList(stdout, stderr), processListener::onExit), "exit-waiter", isDaemon));
} }
@@ -652,10 +667,12 @@ public class DefaultLauncher extends Launcher {
private static final class Command { private static final class Command {
final CommandBuilder commandLine; final CommandBuilder commandLine;
final Path tempNativeFolder; final Path tempNativeFolder;
final Charset encoding;
Command(CommandBuilder commandBuilder, Path tempNativeFolder) { Command(CommandBuilder commandBuilder, Path tempNativeFolder, Charset encoding) {
this.commandLine = commandBuilder; this.commandLine = commandBuilder;
this.tempNativeFolder = tempNativeFolder; this.tempNativeFolder = tempNativeFolder;
this.encoding = encoding;
} }
} }
} }

View File

@@ -112,6 +112,7 @@ public final class JavaVersion {
public static final int JAVA_8 = 8; public static final int JAVA_8 = 8;
public static final int JAVA_9 = 9; public static final int JAVA_9 = 9;
public static final int JAVA_16 = 16; public static final int JAVA_16 = 16;
public static final int JAVA_17 = 17;
private static int parseVersion(String version) { private static int parseVersion(String version) {
Matcher matcher = VERSION.matcher(version); Matcher matcher = VERSION.matcher(version);