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 服务器上。
附加信息:
- 我使用从 Visual Studio 2022 年启动的 IIS Express 和一个外部 WAMPServer 作为调试服务器。都输出乱码结果。
- PHP的版本是8.1.
- OS是Windows11家企业。
- 我的 PHP 文件正确保存为 UTF-8(无 BOM)
- 重要说明 1:在从 PowerShell 7.2 64 位打开的 PHP 交互式 shell 中,原始代码 有效 。
- 重要说明 2:原始代码 可以在另一台使用 Windows 10 Home.
的计算机上运行
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,检查输出 .
以下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 服务器上。
附加信息:
- 我使用从 Visual Studio 2022 年启动的 IIS Express 和一个外部 WAMPServer 作为调试服务器。都输出乱码结果。
- PHP的版本是8.1.
- OS是Windows11家企业。
- 我的 PHP 文件正确保存为 UTF-8(无 BOM)
- 重要说明 1:在从 PowerShell 7.2 64 位打开的 PHP 交互式 shell 中,原始代码 有效 。
- 重要说明 2:原始代码 可以在另一台使用 Windows 10 Home. 的计算机上运行
TLTR
使用PHP函数sapi_windows_cp_conv
如下。
$res = stream_get_contents($pipes[1]);
$res = sapi_windows_cp_conv(sapi_windows_cp_get('ansi'), 65001, $res);
长答案
解决办法参考这个
首先,尝试修改these steps之后cmd.exe的默认代码页。但是,如果编码问题仍然存在,您可能需要查看下一个备选方案。
要强制从一个代码页直接从 PHP 转换为另一个代码页,请使用 sapi_windows_cp_conv(sapi_windows_cp_get($kind), 65001, $res)
,其中 65001 指的是 UTF-8 编码(请参阅 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,检查输出