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

时间:2011-11-30 18:58:43

标签: php character-encoding stdin fgets

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

我在Windows 7下使用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,当我键入å并打印“&gt;å”时,循环不会中断,但“ÅÄÖåäö在这里工作”变为“Ã...ÔÃ- åöö在这里工作!“而且我知道我可以将文件更改为ANSI,但是我不能使用像╠╦╗这样的特殊字符。

那么为什么在输入åäö之后fgets会停止等待用户输入?

我该如何解决这个问题?

编辑:

还发现了一个奇怪的bug。 echo "öäåÅÄÖåäö work here! Or?".chr(10); - &gt; ��äåÅÄÖåäö work here! Or? re! Or?。 如果echo中的第一个char是å/ä/ö,它会打印出奇怪的字符,并且结尾输出副本带有n - 1 char ..(n =字符串开头的åäö的数字)。

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

EDIT2(已解决):

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

2 个答案:

答案 0 :(得分:5)

可能的解决方案:

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是Win XP SP3 32位

您可以尝试升级PHP。

我下载了php-5.3.5-nts-Win32-VC6-x86并且无法重现您的错误,它对我来说很好。

编辑:Additionaly我使用我的西班牙语键盘输入了字符。

EDIT2:

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
öïü

öïü
>öïü

答案 1 :(得分:2)

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

这些字符:ÅÄÖåäö

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

引用PHP String

  

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

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

MB functions处理多字节字符串基本操作。

相关问题