Как читать символы, отличные от ASCII, из стандартного ввода CLI

Если я наберу å в CMD, fgets перестанет ждать ввода, и цикл будет работать до тех пор, пока я не нажму ctrl-c. Если я наберу «обычные» символы, такие как a-z0-9!?(), он будет работать, как и ожидалось.

Я запускаю код в CMD под Windows 7 с кодировкой UTF-8 (chcp 65001), файл сохраняется как UTF-8 без bom. Я использую PHP 5.3.5 (cli).

<?php

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

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

?>

Если я изменю кодировку на chcp 1252, цикл не прерывается, когда я набираю å и печатаю «> å», но «ÅÄÖåäö work here» становится «Ã…ÄÖåäö work here!». И я знаю, что могу изменить файл на ANSI, но тогда я не могу использовать специальные символы, такие как ╠╦╗.

Почему же fgets перестает ждать ввода данных пользователем после того, как я набрал åäö?

И как это исправить?

РЕДАКТИРОВАТЬ:

Также обнаружил странный баг. echo "öäåÅÄÖåäö work here! Or?".chr(10); -> ��äåÅÄÖåäö work here! Or? re! Or?. Если первый символ в эхе равен å/ä/ö, он печатает странные символы И в конце выводятся дубликаты с n - 1 символами.. (n = количество символов åäö в начале строки).

Например: echo "åäö 1234" -> ??äö 123434 и echo åäöåäö 1234 -> ??äöåäö 1234 1234.

EDIT2 (решено):

Проблема была chcp 65001, сейчас использую chcp 437 (chcp 437). Большое спасибо Тимоти Мартенсу!


person Sawny    schedule 30.11.2011    source источник
comment
Несколько вопросов по этой проблеме: 1) что происходит, когда вы пытаетесь ввести и å в CMD вне php? 2) Логично, что UTF-8 Å не совпадает с Windows-1252 Å, поэтому в результате получается Ã. Но что произойдет, если вы попытаетесь преобразовать файл PHP в Windows-1252?   -  person Qqwy    schedule 02.12.2011
comment
1) åäö -› команда не нравится, эхо åäö -› ääö. Так что это работает. Как с chcp 65001 (UTF-8), так и с chcp 1252. 2) Я использую UTF-8 в cmd И в качестве кодировки для файла PHP. Если я использую windows-1252 в файле PHP, ничего не меняется. Я думаю, что проблема в Windows/PHP. Когда я использую chcp 1252, он работает для ÅÄÖ (даже если файл PHP имеет кодировку UTF-8), но тогда я не могу использовать ╠╦╗ и т. д.   -  person Sawny    schedule 03.12.2011
comment
Чувак, какой интересный вопрос ^^. Ты действительно привлек мое внимание сейчас. Я собираюсь немного поэкспериментировать и сообщу вам, как только что-нибудь найду.   -  person Qqwy    schedule 03.12.2011
comment
Интересно... что, если бы вы использовали fgetsc(STDIN)? Вероятно, то же самое, но это может привести к другому (нежелательному? :P) результату...   -  person Qqwy    schedule 03.12.2011
comment
@Qqwy var_dump(fgetc(STDIN)) -> bool(false); var_dump(fgets(STDIN)) -> bool(false); когда я набираю å (или äö). Иначе это работает.   -  person Sawny    schedule 03.12.2011


Ответы (2)


Возможное решение:

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

Примечания. Мне не удалось воспроизвести вашу ошибку, используя несколько версий PHP. Использование следующей версии PHP 5.3.8 не вызвало у меня проблем

PHP 5.3 (5.3.8) VC9 x86 Non Thread Safe (2011-Aug-23 12:26:18) Architechture - это 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
öïü

öïü
>öïü
person Timothy Martens    schedule 08.12.2011
comment
1) stream_get_line не работает. 2) Я скачал VC9 x86 Non Thread Safe (2011-Aug-23 12:26:18) сейчас, но это не сработало. Какую кодировку вы использовали в CMD и в своем коде? Кстати, я запускаю W7 64bit. - person Sawny; 08.12.2011
comment
@Timoth Martens В Windows cmd не будет ли это stream_get_line(STDIN, 999999, PHP_EOL);? Я все равно обновил ваш ответ. +1 в любом случае. кажется лучшим решением на данный момент. - person Yes Barry; 09.12.2011
comment
ПРИМЕЧАНИЕ. Я только что проверил это на своем Mac, используя PHP 5.3.6 и PHP 5.2.14, и оба работали. - person Yes Barry; 09.12.2011
comment
@mmmshuddup К сожалению, это не работает для меня :( Можете ли вы опубликовать свой код и свою кодировку (как консольную, так и кодовую)? Поскольку я тестировал ansi/utf8 utf8/utf8 utf8/ansi со всеми решениями, размещенными здесь, я думаю ... ни одно из них не работает для меня. - person Sawny; 09.12.2011
comment
@Sawny, который я использую в cmd. Активная кодовая страница: 437. Вы можете изменить свою, запустив chcp 437 в cmd. - person Timothy Martens; 09.12.2011
comment
интересно а что у вас??? Вы можете обнаружить это, просто запустив команду в cmd chcp. Я нашел этот вопрос на chcp, если вам нужна дополнительная информация: stackoverflow.com/questions/1259084/ - person Timothy Martens; 09.12.2011
comment
@Sawny Любопытно, что когда я набираю обычные буквы, php сообщает, что он обнаруживает ANSI, но когда я набираю специальные символы, PHP ничего не сообщает. Я использую mb_detect_encoding(), чтобы сказать мне, что такое кодировка. - person Timothy Martens; 09.12.2011

Я думаю, это происходит потому, что PHP 5.3 не поддерживает должным образом многобайтовые символы.

Эти символы: ÅÄÖåäö

Двоичные: c3 85 c3 84 c3 96 c3 a5 c3 a4 c3 b6 (без спецификации в начале)

Ссылаясь на строку PHP:

Строка представляет собой последовательность символов, где символ совпадает с байтом. Это означает, что PHP поддерживает только набор из 256 символов и, следовательно, не предлагает встроенной поддержки Unicode. См. подробности о строковом типе.

Обычно не влияет на конечный результат, потому что браузер/читатель понимает многобайтовые символы, но для CMD и STDIN буфер равен ÅÄÖåäö (массив символов 12 символов/байт).

только функции MB обрабатывают основные операции с многобайтовыми строками.

person Paulo H.    schedule 08.12.2011
comment
Да, я знаю о функциях MB, но у них нет функции чтения ресурсов :( - person Sawny; 08.12.2011