PHP:如何配置 Windows shell 代码页以使 proc_open() 的 STDOUT 不会出现乱码?

发布于 2025-01-14 15:50:38 字数 1704 浏览 0 评论 0 原文

以下 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。也就是说,我将上述代码片段的第三行替换为

$encoding = array('LANG'=>'ja_JP.utf-8');
$proc = proc_open($cmd, $descriptorspec, $pipes, null, $encoding);

Still 输出乱码字符串 $res = ����ɂ���

接下来,我尝试按照 此解决方案。第一个片段的第三行变成

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

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

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

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

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

其他信息:

  • 我使用从 Visual Studio 2022 启动的 IIS Express 和外部 WAMPServer 作为调试服务器。两者都输出乱码。
  • PHP 版本是 8.1。
  • 操作系统是 Windows 11 Enterprise。
  • 我的 PHP 文件正确保存为 UTF-8 (无 BOM)
  • 重要说明 1:原始代码在从 PowerShell 7.2 64 位打开的 PHP 交互式 shell 中有效
  • 重要说明2:原始代码可以在另一台使用 Windows 10 家庭版的计算机上运行

The following PHP code

$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;

outputs the gibberish $res = ����ɂ���.

I tried this solution by setting up $env_vars in proc_open(). That is, I substituted the third line of the above snippet with

$encoding = array('LANG'=>'ja_JP.utf-8');
$proc = proc_open($cmd, $descriptorspec, $pipes, null, $encoding);

Still outputs the garbled string $res = ����ɂ���.

Next, I tried to use setlocale() and putenv() as per this solution. The third line of the first snippet becomes

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

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

Still outputs the gibberish $res = ����ɂ���...

Do you know what's wrong with the shell encoding config?

As a side note, I'm currently debugging my code on Visual Studio 2022 with IIS Express (Win10/11), but will eventually deploy my website on an Apache server.

Additional info:

  • I use IIS Express launched from Visual Studio 2022 and an external WAMPServer as debugging servers. Both output garbled results.
  • The version of PHP is 8.1.
  • The OS is Windows 11 Enterprise.
  • My PHP file is correctly saved in UTF-8 (without BOM)
  • Important note 1: the original code works in the PHP interactive shell opened from PowerShell 7.2 64bits.
  • Important note 2: the original code works on another computer using Windows 10 Home.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

执着的年纪 2025-01-21 15:50:38

TLTR

使用 PHP 函数 sapi_windows_cp_conv,如下所示。

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

长答案

解决方案指的是这个 SO回答。事实上,PHP 与 Windows 的默认命令 shell(cmd.exe、pwsh.exe...)进行通信,其代码页可能设置为 ANSI 而不是 UTF-8。

首先,尝试按照 这些步骤。但是,如果编码问题仍然存在,您可能需要考虑下一个替代方案。

要直接从 PHP 强制执行从一个代码页到另一个代码页的转换,请使用 sapi_windows_cp_conv(sapi_windows_cp_get($kind), 65001, $res),其中 65001 指 UTF-8 编码(请参阅chcp)。请参阅sapi_windows_cp_conv文档这里。请注意,$kind 需要根据 'ansi' 或 'oem' .php.net/manual/en/function.sapi-windows-cp-get.php" rel="nofollow noreferrer">文档

编辑:要将 cmd/powershell 的 ANSI/OEM 设置为 UTF-8 在系统级别,请查看 这些步骤

TLTR

Use the PHP function sapi_windows_cp_conv as follows.

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

Long Answer

The solution refers to this SO answer. In fact, PHP communicates with the default command shell of windows (cmd.exe, pwsh.exe, ...), whose codepage might be set to ANSI instead of UTF-8.

First, try to modify the default codepage of cmd.exe following these steps. However, if encoding issues persist, you might need to look at the next alternative.

To enforce conversion from one codepage to another directly from PHP, use sapi_windows_cp_conv(sapi_windows_cp_get($kind), 65001, $res), where 65001 refers to UTF-8 encoding (see chcp). 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.

EDIT: To set ANSI/OEM of cmd/powershell to UTF-8 at the system level, check out these steps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文