记一次 electron 添加 检测 终端编码,解决终端打印中文乱码问题

前言:

electron 终端打印中文乱码,但有些同事终端 编码 是 urf8 , 有些是 gbk,所以添加编码检测,保证所有人终端打印中文不乱码

采用了 winston 日志库

使用 iconv-lite 库来进行字符编码转换。

iconv-lite

1. 关键逻辑 (可以 cmd/powerShell 输入 chcp 查看当前编码集)

常见 Windows 代码页:

437 → 美国英语(OEM US)

936 → 简体中文(GBK/GB2312)

950 → 繁体中文(Big5)

65001 → UTF-8

判断代码:
ts 复制代码
    const output = execSync('chcp', { encoding: 'utf8' }).toLowerCase().trim();

    if (output.includes('65001')) {
      return 'utf8';
    }
    if (output.includes('936')) {
      return 'gbk';
    }

2.核心片段

typescript 复制代码
/* eslint-disable @typescript-eslint/no-explicit-any */
import winston from 'winston';
import { format, TransformableInfo } from 'logform';
import DailyRotateFile from 'winston-daily-rotate-file';
import * as Transport from 'winston-transport';
import iconv from 'iconv-lite';
import { safeFormat } from 'shared/static.tools';
import { LogLevel } from 'shared/types';
import { DEFULT_LABEL } from './type';
import { execSync } from 'child_process';


/**
 * 自动探测当前终端编码
 */
type SupportedEncoding = 'utf8' | 'gbk';

function detectEncoding(): SupportedEncoding {
  try {
    if (process.platform !== 'win32') {
      return 'utf8'; // macOS / Linux 默认 UTF-8
    }
    // Windows: 检查 code page
    const output = execSync('chcp', { encoding: 'utf8' }).toLowerCase().trim();

    if (output.includes('65001')) {
      return 'utf8';
    }
    if (output.includes('936')) {
      return 'gbk';
    }
  } catch {
    // 如果 execSync 出错,走默认
  }
  return 'utf8';
}

/**
 * 自定义 ConsoleTransport:自动转码,解决 Windows 控制台中文乱码
 */
class EncodedConsoleTransport extends Transport {
  private _encoding: SupportedEncoding;

  constructor(opts?: Transport.TransportStreamOptions) {
    super(opts);
    this._encoding = detectEncoding(); // 初始化时就探测好
  }

  override log(info: any, callback: () => void): void {
    setImmediate(() => this.emit('logged', info));

    let formatted = `${info.timestamp} [${info.level}]`;
    if (info.label && info.label !== DEFULT_LABEL) {
      formatted += ` [${String(info.label).substring(0, 9)}]`;
    }
    formatted += `: ${info.message}`;

    const encodedBuffer = iconv.encode(formatted + '\n', this._encoding);
    process.stdout.write(encodedBuffer);

    callback();
  }
}

const consoleTransport = new EncodedConsoleTransport({
  level: 'debug',
});

const transports: Transport[] = [consoleTransport];

const winstonLogger = winston.createLogger({
  format: format.combine(
    format.timestamp({ format: 'HH:mm:ss.SSS' }),
    format.colorize(), // 不同等级 level 的日志上色(info=绿色,warn=黄色,error=红色)
    format.splat(), // 支持 %s, %d, %j 等格式化
    format.simple() // 简单格式化
  ),
  transports: transports,
});
相关推荐
人机与认知实验室几秒前
<span class=“js_title_inner“>如何看待特斯拉第三代Optimus机器人?</span>
开发语言·javascript·机器人·ecmascript·unix
Doris8934 分钟前
【 Vue】 Vue3全面讲解文档
前端·javascript·vue.js
换日线°4 分钟前
vue 实现Element Plus的炫酷主题切换
javascript·vue.js
linweidong11 分钟前
大厂工程化实践:如何构建可运维、高稳定性的 Flutter 混合体系
javascript·flutter
Hexene...14 分钟前
【前端Vue】如何快速直观地查看引入的前端依赖?名称版本、仓库地址、开源协议、作者、依赖介绍、关系树...(Node Modules Inspector)
前端·javascript·vue.js
fanruitian16 分钟前
div水平垂直居中
前端·javascript·html
旭久19 分钟前
react+antd实现一个支持多种类型及可新增编辑搜索的下拉框
前端·javascript·react.js
摘星编程19 分钟前
用React Native开发OpenHarmony应用:Loading加载状态组件
javascript·react native·react.js
aesthetician29 分钟前
Spotify 网页版前端技术全面解析
前端
咩图30 分钟前
Sketchup软件二次开发+Ruby+VisualStudioCode
java·前端·ruby