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


How to read non-ASCII characters from CLI standard input

如果我在CMD中键入å,fgets将停止等待更多输入,循环将运行,直到我按下ctrl-c。如果我键入"普通"字符,如a-z0-9!?((它按预期工作。

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

<?php
echo "ÅÄÖåäö work here.'n";
while(1)
{
    echo '> '. fgets(STDIN);
}
?>

如果我将字符集更改为chcp 1252,当我键入å并打印">å"时,循环不会中断,但"在这里工作"变成了"在这里!"。我知道我可以将文件更改为ANSI,但我不能使用特殊字符,如╠╦╗.

为什么fgets在我输入åäö后就不再等待用户输入了

我该如何解决

编辑:

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

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

EDIT2(已解决(:

问题是chcp 65001,现在我使用chcp 437(chcp 437(。非常感谢Timothy Martens!

可能的解决方案:

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

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

PHP 5.3(5.3.8(VC9x86非线程安全(2011年8月23日12:26:18(Arcitechture是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
öïü
öïü
>öïü

我认为这是因为PHP 5.3不支持正确的多字节字符。

这些字符:ÅÄÖåäö

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

引用PHP字符串:

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

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

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