PHP: 如何配置windows shell 代码页使proc_open() 的STDOUT 不乱码?

PHP: How to configure windows shell codepage so that STDOUT of proc_open() does not garble?

以下PHP代码

$descriptorspec = array(1=>array('pipe', 'w'));
$cmd = escapeshellcmd('echo こんにちは');

// Change this line in the following snippets
$proc = proc_open($cmd, $descriptorspec, $pipes);

$res = null;

if (is_resource($proc))
{
    $res = stream_get_contents($pipes[1]);
    proc_close($proc);
}

echo $res;

输出乱码$res = ����ɂ���

我通过在 proc_open() 中设置 $env_vars 来尝试 this solution。也就是说,我用

替换了上面代码片段的第三行
$encoding = array('LANG'=>'ja_JP.utf-8');
$proc = proc_open($cmd, $descriptorspec, $pipes, null, $encoding);

还是输出乱码$res = ����ɂ���.

接下来,我尝试按照 this solution 使用 setlocale()putenv()。第一个片段的第三行变成

$encoding = 'ja_JP.UTF-8';
setlocale(LC_ALL, $encoding);
putenv('LC_ALL='. $encoding);

$proc = proc_open($cmd, $descriptorspec, $pipes);

仍然输出乱码$res = ����ɂ���...

你知道 shell 编码配置有什么问题吗?

附带说明一下,我目前正在 Visual Studio 2022 上使用 IIS Express (Win10/11) 调试我的代码,但最终会将我的网站部署到 Apache 服务器上。

附加信息:

TLTR

使用PHP函数sapi_windows_cp_conv如下。

$res = stream_get_contents($pipes[1]);
$res = sapi_windows_cp_conv(sapi_windows_cp_get('ansi'), 65001, $res);

长答案

解决办法参考这个。事实上,PHP 与 windows 的默认命令 shell 通信(cmd.exe、pwsh.exe、...),其代码页可能设置为 ANSI UTF-8.

首先,尝试修改these steps之后cmd.exe的默认代码页。但是,如果编码问题仍然存在,您可能需要查看下一个备选方案。

要强制从一个代码页直接从 PHP 转换为另一个代码页,请使用 sapi_windows_cp_conv(sapi_windows_cp_get($kind), 65001, $res),其中 65001 指的是 UTF-8 编码(请参阅 ). Please refer to the sapi_windows_cp_conv documentation here. Note that $kind needs to be specified as 'ansi' or 'oem' as per the documentation

编辑:要在系统级别将cmd/powershell的ANSI/OEM设置为UTF-8,检查输出 .