如何从 CLI 标准输入中读取非 ASCII 字符

2022-08-31 01:21:02

如果我键入CMD,fgets停止等待更多输入,循环运行,直到我按.如果我键入一个“正常”字符,如a-z0-9!?() 它按预期工作。åctrl-c

我在Windows 7下的CMD中运行代码,UTF-8作为字符集(),该文件被保存为UTF-8,没有bom。我使用 PHP 5.3.5 (cli)。chcp 65001

<?php

echo "ÅÄÖåäö work here.\n";

while(1)
{
    echo '> '. fgets(STDIN);
}

?>

如果我将字符集更改为循环,则当我键入时不会中断,并且它打印“>å”,但“ÅÄÖåäö在这里工作”变为“Ã...“在这里工作!我知道我可以将文件更改为ANSI,但是我不能使用像╠╦╗这样的特殊字符。chcp 1252å

那么,为什么在我键入 åäö 之后,fgets 会停止等待 userinput 呢?

我该如何解决这个问题?

编辑:

还发现了一个奇怪的虫子。 -> .如果回声中的第一个字符是它打印奇怪的字符,并且最终输出与字符重复。(n = 字符串开头的 åäö 数)。echo "öäåÅÄÖåäö work here! Or?".chr(10);��äåÅÄÖåäö work here! Or? re! Or?å/ä/ön - 1

例如:和 ->。echo "åäö 1234" -> ??äö 123434echo åäöåäö 1234??äöåäö 1234 1234

编辑2(已解决):

问题是,现在我使用(chcp 437)。非常感谢蒂莫西·马滕斯!chcp 65001chcp 437


答案 1

可能的解决方案:

echo '>'; 
$line = stream_get_line(STDIN, 999999, PHP_EOL);

注意:我无法使用多个版本的PHP重现您的错误。使用以下 PHP 版本 5.3.8 没有给我带来任何问题

PHP 5.3 (5.3.8) VC9 x86 非线程安全 (2011年8月23日 12:26:18) Arcitechture is Win XP SP3 32 位

您可以尝试升级 PHP。

我下载了php-5.3.5-nts-Win32-VC6-x86,无法重现您的错误,它对我来说工作正常。

编辑:另外,我使用西班牙语键盘键入了字符。

编辑2:

CMD 命令:

chcp 437

PHP 代码:

<?php
$fp=fopen("php://stdin","r");
while(1){
    $str =  fgets(STDIN);
    echo mb_detect_encoding($str)."\n";
    echo '>'.stream_get_line($fp,999999,"\n")."\n";
}
?>

输出:

test
ASCII
test
>test
öïü

öïü
>öïü

答案 2

我认为发生这种情况是因为PHP 5.3不支持正确的多字节字符。

这些字符:ÅÄÖåäö

是二进制的:(开始时没有 BOM)c3 85 c3 84 c3 96 c3 a5 c3 a4 c3 b6

引用 PHP 字符串

字符串是一系列字符,其中字符与字节相同。这意味着 PHP 仅支持 256 个字符集,因此不提供本机 Unicode 支持。请参阅字符串类型的详细信息。

通常不会影响最终结果,因为浏览器/阅读器理解多字节字符,但对于CMD和STDIN缓冲区是(12个字符/字节字符数组)。ÅÄÖåäö

只有 MB 函数处理多字节字符串的基本操作。


推荐