V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ubuntuGary
V2EX  ›  Java

如何解决 LogOutputStream 中文乱码问题?

  •  
  •   ubuntuGary · 2022-04-15 17:17:40 +08:00 · 1579 次点击
    这是一个创建于 990 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不管是 org.apache.commons.exec 工具包,还是 org.zeroturnaround.exec 工具包,都会出现中文乱码问题,请问有办法解决吗? 例子: org.apache.commons.exec 工具包的 demo:

    package utils.exec;
    
    import cn.hutool.core.io.LineHandler;
    import lombok.NonNull;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.exec.*;
    
    import java.util.concurrent.TimeUnit;
    
    @Slf4j
    public class LocalCommandUtils {
        private static final long TIMEOUT = 1;
        private static final TimeUnit TIME_UNIT = TimeUnit.DAYS;
    
        public static String execCmd(String cmd) {
            return execCmd(cmd, line -> {});
        }
    
        public static String execCmd(String cmd, LineHandler lineHandler) {
            return execCmd(cmd, lineHandler, TIMEOUT, TIME_UNIT);
        }
    
        public static String execCmd(String cmd, LineHandler lineHandler, @NonNull long timeout, @NonNull TimeUnit unit) {
            DefaultExecutor executor = new DefaultExecutor();
            ExecuteWatchdog watchdog = new ExecuteWatchdog(unit.toMillis(timeout));
            StringBuilder output = new StringBuilder();
            try {
                CommandLine cmdLine = CommandLine.parse(cmd);
                executor.setWatchdog(watchdog);
                executor.setStreamHandler(new PumpStreamHandler(new LogOutputStream() {
                    @Override
                    protected void processLine(String line, int logLevel) {
                        lineHandler.handle(line);
                        output.append(output.length() > 0 ? "\n" : "").append(line);
                    }
                }));
                executor.execute(cmdLine);
                log.info("exec command:[{}] output:[\n{}\n]", cmd, output);
            } catch (Exception e) {
                log.error("exec command:[{}] failed, output:[\n{}\n]", cmd, output, e);
            }
            return output.toString();
        }
    
        public static void main(String[] args) {
            execCmd("ping 127.0.0.1", log::info);
        }
    }
    
    

    org.zeroturnaround.exec 工具包的 demo:

    package utils.ztexec;
    
    import cn.hutool.core.io.LineHandler;
    import lombok.NonNull;
    import lombok.extern.slf4j.Slf4j;
    import org.zeroturnaround.exec.ProcessExecutor;
    import org.zeroturnaround.exec.stream.LogOutputStream;
    
    import java.util.concurrent.TimeUnit;
    
    @Slf4j
    public class LocalCommandUtils {
        private static final long TIMEOUT = 1;
        private static final TimeUnit TIME_UNIT = TimeUnit.DAYS;
    
        public static String execCmd(String cmd) {
            return execCmd(cmd, line -> {});
        }
    
        public static String execCmd(String cmd, LineHandler lineHandler) {
            return execCmd(cmd, lineHandler, TIMEOUT, TIME_UNIT);
        }
    
        public static String execCmd(String cmd, LineHandler lineHandler, @NonNull long timeout, @NonNull TimeUnit unit) {
            StringBuilder output = new StringBuilder();
            try {
                new ProcessExecutor()
                        .commandSplit(cmd)
                        .timeout(timeout, unit)
                        .redirectOutput(new LogOutputStream() {
                            @Override
                            protected void processLine(String line) {
                                lineHandler.handle(line);
                                output.append(output.length() > 0 ? "\n" : "").append(line);
                            }
                        })
                        .execute();
                log.info("exec command:[{}] output:[\n{}\n]", cmd, output);
            } catch (Exception e) {
                log.error("exec command:[{}] failed, output:[\n{}\n]", cmd, output, e);
            }
    
            return output.toString();
        }
    
        public static void main(String[] args) {
            execCmd("ping 127.0.0.1", log::info);
        }
    }
    
    2 条回复    2022-04-16 17:55:49 +08:00
    ec0
        1
    ec0  
       2022-04-16 02:18:35 +08:00   ❤️ 1
    研究了一下
    这两个工具包在 github 上的代码,LogOutputStream 类都有设置 charset 的方法,但是是后来( 2020 、2021 年)加入的功能

    而 maven 仓库里的版本(一个停留在 2014 年,一个停留在 2020 年)都没有设置 charset 的方法

    所以你可以

    1. 寻找其他的工具包

    2. 抄 github 上的代码,比如

    2.1 新建一个类 LogOutputStream ,把

    https://github.com/zeroturnaround/zt-exec/blob/master/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java

    里的代码复制过去

    2.2 将 import org.zeroturnaround.exec.stream.LogOutputStream; 改成 import 你自己的 LogOutputStream

    2.3 在 new LogOutputStream 时设置 charset ,new LogOutputStream() {}.setOutputCharset("GBK")
    ubuntuGary
        2
    ubuntuGary  
    OP
       2022-04-16 17:55:49 +08:00
    @ec0 非常感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1072 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:34 · PVG 03:34 · LAX 11:34 · JFK 14:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.