将扩展的 Ascii“表格”代码(例如 ─、┬)从 Php 脚本打印到控制台时出现问题

Posted

技术标签:

【中文标题】将扩展的 Ascii“表格”代码(例如 ─、┬)从 Php 脚本打印到控制台时出现问题【英文标题】:Issues with printing extended Ascii "table" codes (e.g. ─, ┬) to console from Php script 【发布时间】:2017-08-12 11:21:30 【问题描述】:

更新

我在下面的答案中添加了该问题的解决方案。此外,标题已从旧更新为更合适的标题,因为似乎从 128 到 255 的所有字符似乎都导致了问题(扩展的 ASCII 代码,如下所示:Ascii table)。

更新二

在将 PHP 更新到 7.1.30 后问题似乎已经消失(较低版本可能也可以)。 值得注意的是,我在下面的修复反而在新版本中导致了有问题的输出: 同样在答案中使用辅助函数显然会导致问题,因为它会产生乱码:

for($i=128; $i<256; $i++) echo "'" . chr($i) . "', ";
'�', '�', '�', '�', '�', '�',...

我已经测试过在 5.6.25 和 7.1.30 之间来回切换,但问题再次出现在 5.6 中。并且该修复在 5.6 中运行良好,因此显然与版本相关。

结论

问题似乎是由 php 版本引起的 - 以前是 5.6.25,现在是 7.1.30,不再需要修复(也不可取,因为它会导致问题)。 因此,如果您遇到ÔöÇ 问题并且您运行的是较低的 PHP 版本,那么该修复程序可能会对您有所帮助。但如果你遇到,问题就出在其他地方。


旧的描述:

我正在尝试输出从 Laravel Artisan 命令运行的 gulp 任务的结果(我需要来自 PHP 的数据来编译,然后从多个模块中导出资产,然后在主应用程序中将它们全部编译)。

一切正常,但由于某种原因,“表格”Ascii 字符被错误地输出为乱码 (Ôöî) 而不是正确的字符 ()。

详情

查看此图像:,并将其与直接从 gulp 输出到控制台的相同命令输出的所需结果进行比较:。

所以我对此进行了修改,有趣的是,即使我只是在我的 php 文件(由 Laravel artisan 作为 php artisan my-command 运行)中使用 echo "─┬──────────────"; ,我也会得到错误的结果。错误的结果是ÔöÇÔöČÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇ

我尝试过转换编码(mb_convert_encoding("─┬──────────────", "UTF-8")),检测编码(php 状态为“UTF-8”),设置配置值(ini_set output_encoding, internal_encoding, ...)并尝试了其他各种方法。无济于事...

所以我更深入地尝试在我的脚本和命令行中使用ord()chr() 来确定真正发生了什么。所以:当我在命令行中运行它时:

$php -a
Interactive mode enabled

<?php
$var = "─┬──────────────";
for($i = 0; $i < strlen($var); $i++)     echo ord($var[$i])."<br/>"; 
?>

我得到196&lt;br/&gt;194&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt;196&lt;br/&gt; &lt;br/&gt; 是从另一个线程复制粘贴的,在这种情况下它是一个好的视觉分隔符)

但是当我从文件运行完全相同的代码时(通过 php artisan 命令运行),我得到226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;172&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;226&lt;br/&gt;148&lt;br/&gt;128&lt;br/&gt;

所以我得到226 148 128(不正确)而不是所需的196。当我尝试 echo chr(196) 时,它会打印正确的字符,即使是通过 Artisan 运行的脚本文件(它会打印 )。

此外,当将 php 脚本文件的输出记录到日志文件时(通过 Laravel 的 \Log::info() ),我确实得到了正确的结果。

仅当从文件运行脚本并打印到控制台时才会出现问题。

结论

你知道发生了什么吗?

为什么所有其他字符都正确打印出来,甚至错误的字符在日志中也正确打印,但错误地打印到控制台?

我相信这个问题与 Gulp 无关,很可能与 Artisan 无关。这很可能是某种编码问题。

任何帮助将不胜感激。

我没有想法......

更多信息

包含脚本的文件以 UTF-8 编码。

我使用以下代码运行 gulp 任务,但我相当确定这与实际问题无关:

    $proc = popen($command, 'r');
    while (!feof($proc))
    
        $fread = mb_convert_encoding(fread($proc, 4096), 'utf-8');

        \Log::info($fread);

        print($fread);
        @ flush();
    

    pclose($proc);

我在 Windows 10 操作系统上使用 cmder 作为控制台模拟器。

编辑我:

我从终端中的 ord() 获得了代码。

ord("─") 如果在终端中运行,则返回 196

php -a
Interactive mode enabled

<?php
echo (ord("─"));
?>
^Z
196

我可以通过在脚本文件中显式使用 echo chr(196) 来输出正确的字符,但是 echo "─" 会打印垃圾。

编辑二:

如果我运行chcp,我会得到Active code page: 852

如果我使用

    $string = "─┬──────────────";
    $string = mb_convert_encoding($string, "windows-1252");

我得到???????????????? 作为脚本的输出。

如果我使用$string = mb_convert_encoding($string, "ISO-8859-1");,我会得到相同的结果。

为什么所有其他字符都正确打印? (见我上面的第一张图片↑)。所有字母,所有颜色,所有格式都可以,除了那几个特殊字符。


我正在考虑在我打印的每一行上运行 str_replace() 以用我想要的替换我得到的。

或者只是忽略输出的格式。它很丑,但它是可读的......

【问题讨论】:

您在不使用 UTF-8 的终端上的输出是 UTF-8,但可能是一些 8 位编码,例如 ISO-8859-1 (Latin-1) 或其表亲之一。更改您的终端设置,或更改您的脚本以输出正确的编码。请注意,字符 >= 128 不是 ASCII(ASCII 为 7 位,在 127 处停止)。 当您运行 Windows 时,很可能是 windows-1252 编码。 @jcaron 我认为他的意思是“ASCII 艺术”。在为 Windows-1252 设置的 Windows 中,控制台可能是 CP437。 @Jan Go chcp. 你从哪里得到这些字符代码? 试试这个cmder讨论。顺便说一句——没有“ 扩展 ASCII”和“在某个时间点在某些网页上显示的扩展 ASCII”是非常随意的。如果您使用的是扩展 ASCII 编码之一,请找出是哪一个。 【参考方案1】:

如果有人遇到同样的问题,这个功能可以解决问题:

 /**
 * Fixes the extended ASCII characters incorrectly displayed into console.
 *
 * @param string $text
 *
 * @return string
 */
function convertExtendedAsciiCharacters($text)

    return str_replace(
        ['Ç', 'ü', 'é', 'â', 'ä', 'ů', 'ć', 'ç', 'ł', 'ë', 'Ő', 'ő', 'î', 'Ź', 'Ä', 'Ć', 'É', 'Ĺ', 'ĺ', 'ô', 'ö', 'Ľ', 'ľ', 'Ś', 'ś', 'Ö', 'Ü', 'Ť', 'ť', 'Ł', '×', 'č', 'á', 'í', 'ó', 'ú', 'Ą', 'ą', 'Ž', 'ž', 'Ę', 'ę', '¬', 'ź', 'Č', 'ş', '«', '»', '░', '▒', '▓', '│', '┤', 'Á', 'Â', 'Ě', 'Ş', '╣', '║', '╗', '╝', 'Ż', 'ż', '┐', '└', '┴', '┬', '├', '─', '┼', 'Ă', 'ă', '╚', '╔', '╩', '╦', '╠', '═', '╬', '¤', 'đ', 'Đ', 'Ď', 'Ë', 'ď', 'Ň', 'Í', 'Î', 'ě', '┘', '┌', '█', '▄', 'Ţ', 'Ů', '▀', 'Ó', 'ß', 'Ô', 'Ń', 'ń', 'ň', 'Š', 'š', 'Ŕ', 'Ú', 'ŕ', 'Ű', 'ý', 'Ý', 'ţ', '´', '­', '˝', '˛', 'ˇ', '˘', '§', '÷', '¸', '°', '¨', '˙', 'ű', 'Ř', 'ř', '■', ' '],
        [chr(128), chr(129), chr(130), chr(131), chr(132), chr(133), chr(134), chr(135), chr(136), chr(137), chr(138), chr(139), chr(140), chr(141), chr(142), chr(143), chr(144), chr(145), chr(146), chr(147), chr(148), chr(149), chr(150), chr(151), chr(152), chr(153), chr(154), chr(155), chr(156), chr(157), chr(158), chr(159), chr(160), chr(161), chr(162), chr(163), chr(164), chr(165), chr(166), chr(167), chr(168), chr(169), chr(170), chr(171), chr(172), chr(173), chr(174), chr(175), chr(176), chr(177), chr(178), chr(179), chr(180), chr(181), chr(182), chr(183), chr(184), chr(185), chr(186), chr(187), chr(188), chr(189), chr(190), chr(191), chr(192), chr(193), chr(194), chr(195), chr(196), chr(197), chr(198), chr(199), chr(200), chr(201), chr(202), chr(203), chr(204), chr(205), chr(206), chr(207), chr(208), chr(209), chr(210), chr(211), chr(212), chr(213), chr(214), chr(215), chr(216), chr(217), chr(218), chr(219), chr(220), chr(221), chr(222), chr(223), chr(224), chr(225), chr(226), chr(227), chr(228), chr(229), chr(230), chr(231), chr(232), chr(233), chr(234), chr(235), chr(236), chr(237), chr(238), chr(239), chr(240), chr(241), chr(242), chr(243), chr(244), chr(245), chr(246), chr(247), chr(248), chr(249), chr(250), chr(251), chr(252), chr(253), chr(254), chr(255)],
        $text);

该函数是使用以下命令生成的:

for($i=128; $i<256; $i++) echo "'" . chr($i) . "', ";
for($i=128; $i<256; $i++) echo "chr($i), ";

如果您缺少某些字符,您可能需要自己生成一个。(见答案末尾)。

结论:

这对我来说似乎是一个可以接受的解决方案,因为它应该相当快并且可以解决问题。

更多细节:

由于这个问题让我很恼火,我一直在修改输出和我的开发设置。似乎问题出在 PHP 输出和控制台之间。扩展 ASCII 表中的任何字符似乎都不起作用 (Ascii table)。 因此我更改了问题的名称以更好地描述问题。

php.ini 中没有任何更改有帮助,所以我决定使用这个简单快速的替换。

如果有人对如何解决问题有更好的想法,我很想听听。

值得注意的是,我的命令行打印的某些字符与上述 Ascii 表中的字符不同。这可能是问题的原因,但仍然没有让我知道如何解决它。

【讨论】:

以上是关于将扩展的 Ascii“表格”代码(例如 ─、┬)从 Php 脚本打印到控制台时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

扩展的 ASCII 字符,例如欧元符号被转换为其 unicode 等价物

将扩展的 ASCII 字符串转换为印地语文本

将表格内容转储为 ASCII 格式的表格字符串的简单方法?

将非 ASCII 字符从 ASCII-8BIT 转换为 UTF-8

字符扩展ascii显示PHP

如何使用 Perl 在文件中查找扩展的 ASCII 字符?