2012-02-20 13 views
14

非ブロッキングであるPHPでSTDINから読み取るためにとにかくがあります:PHP CLIでSTDINにノンブロッキング

私はこの試みた:

stream_set_blocking(STDIN, false); 
echo fread(STDIN, 1); 

と、この:

$stdin = fopen('php://stdin', 'r'); 
stream_set_blocking($stdin, false); 
echo 'Press enter to force run command...' . PHP_EOL; 
echo fread($stdin, 1); 

をそれでもブロックするとfreadがデータを取得します。

これは(7歳)に関するいくつかのオープンなバグレポートに気づきました。それでできない場合は、これを達成できる粗末なハッキングを誰かが知っていますか?

+3

ノンブロッキングの動作を理解しているかどうかわかりません。 stdinへの入力を待機するものがない場合、 'fread()'はFALSEを返しますか?どのようにそれをEOFと区別するのでしょうか?記述的な失敗がないので、stdinで待機中のデータがあるかどうかを判断するためには、fread()以外のテスト*その他*が必要です。 – Graham

+0

@Graham 'fread'は、入力がSTDINに渡されるまで、スクリプトの実行を一時停止します。基本的に私が望むのは、 'STDIN'へのユーザ入力があるかどうかをチェックし、そうでなければ続行するか、他のものを実行することです。 – Petah

+0

@Graham "非ブロック"とは、データの量を読み込めなかったとしても(2番目の引数)、それより少ないデータを読み込むことができる 'fread()'を即座に返さなければならないことを意味します。この場合、空の文字列を返す必要があります。 @Petahは 'fopen( 'php:// stdin)'を試しましたか?ぼんやりと覚えています。以前は「STDIN」の問題がありました。 – KingCrunch

答えて

12

ここに私が思いつくことができます。それはLinuxでうまく動作しますが、Windowsでは、キーを押すとすぐに、入力が押されるまで入力がバッファされます。私は現在、ストリーム、または特にPHPのSTDINでバッファリングを無効にする方法を見つけようとしています。

<?php 

function non_block_read($fd, &$data) { 
    $read = array($fd); 
    $write = array(); 
    $except = array(); 
    $result = stream_select($read, $write, $except, 0); 
    if($result === false) throw new Exception('stream_select failed'); 
    if($result === 0) return false; 
    $data = stream_get_line($fd, 1); 
    return true; 
} 

while(1) { 
    $x = ""; 
    if(non_block_read(STDIN, $x)) { 
     echo "Input: " . $x . "\n"; 
     // handle your input here 
    } else { 
     echo "."; 
     // perform your processing here 
    } 
} 

?> 
+0

ありがとう、これは私の場合に動作します。しかし、あなたはそれを(入力キーの事)と一貫して得ることができればさらに良い。より良い答えがない場合、あなたは賞金をあなたに授与します。 – Petah

+0

私はこれを自分のスクリプトに統合しましたが、入力を待たなければならないという事実を除けば、かなりうまくいきます。私はAlt + Tabキーを押すたびに一時停止し、enterを待ちます。 – Petah

+0

ここでこの質問にstubmle'dし、あなたがstream_set_read_buffer(STDIN、0)を使用しているなら動作するかもしれません。既に述べたように、stream_set_blocking(STDIN、false); - 最初のものは、読み込み時にバッファリングされないようにstdinを設定する必要があります.2番目のセットは、非バッファリングとは少し異なります。 –

1

Petah、私は直接のPHP側で助けることはできませんが、私は、私はしばらく前に出会ったの記事を参照することができます名前付きパイプの保留中のデータの存在をシェルスクリプト内でテストすることで、誰かがトランジスタをエミュレートします。魅力的な読書であり、シェルスクリプティングをまったく新しいレベルの気まぐれにしています。 :-)

記事はこちらです:その後、http://www.linusakesson.net/programming/pipelogic/

だから... ...あなたの「粗ハック」要求への答えに、私はあなたが名前付きパイプを介して、あなたのstdioのシャントができたとし、exec()ソースが含まれているツール上記のURLで、パイプ経由で何かが送信されるのを待っているかどうかをテストします。あなたはおそらく、物事に役立ついくつかのラッパー関数を開発したいと思うでしょう。

私は、pipelogicの解決策はLinuxのみであると思っていますが、少なくともUNIX系のオペレーティングシステムが必要です。これがWindows上でどのように達成されるかは考えられません。

+1

申し訳ありませんが、私は本当にこの問題にどのように役立つか分かりません。 – Petah

+0

@Petah - パイプから読み込むnon-blocking fread()は、パイプ上で待っているデータがあるかどうかを確認した後、ブロックfread()を実行する関数によって複製できます。投稿したリンクのツールを使用して、その条件をテストできます。このアプローチは、名前付きパイプの不足のためにWindowsではうまくいかないと私は確信しているので、Windowsの互換性はあなたの質問の条件なので、それ以上は動作しません。 – ghoti

+0

ありがとうとにかく:) – Petah

0

これで、ノンブロッキングSTDINの作業が完了しました。

関連する問題