2012-03-21 12 views
7

ioから非ブロック的な方法で行を読み込もうとしています。ruby​​ non-blocking line read

残念ながらreadlineブロック。私は​​でこれを解決できると思います。ここでは部分的な結果を保存し、バッファに複数の行があるかどうかをチェックします。しかし、このような簡単な作業では少し複雑です。これを行うより良い方法はありますか?

注:私は逆多重化イベント(select)を使用していると私はそれに非常に満足している、私はなど、EventMachineを使用して、スレッドを作成したくない...

答えて

5

私はread_nonblockソリューションだと思いますおそらく行く方法。シンプルで、最大限に効率的ではありません猿パッチのバージョン:

class IO 
    def readline_nonblock 
    rlnb_buffer = "" 
    while ch = self.read_nonblock(1) 
     rlnb_buffer << ch 
     if ch == "\n" then 
     result = rlnb_buffer 
     return result 
     end 
    end  
    end 
end  

そこだけread_nonblockのような、ないデータが準備だので、あなただけのバックnilを取得することを救うために持っている場合は例外をスローなど

+0

ええ、それは私のオリジナルのアイデアだった、そしてそれは私が最終的にやったことだが、私は、私は(できる限りを読みますただ1つの文字ではない)、私はそれがパフォーマンスのために良いと思う。モンクパッチのチップをありがとう;) –

3

この実装は改行で終わらないデータの読み出しを破棄しないことによって、マーク・リードの答えに向上します。

class IO 
    def readline_nonblock 
    buffer = "" 
    buffer << read_nonblock(1) while buffer[-1] != "\n" 

    buffer 
    rescue IO::WaitReadable => blocking 
    raise blocking if buffer.empty? 

    buffer 
    end 
end 
+1

"保証なし" - それはちょっと怖いです。文書化されていない「機能」に頼らないでください。 "私はこれをテストしました" - トーグリー?さまざまな入力方法で?あなたの入力がラインバッファリングされていたからです。 –

+0

私はそれに頼るのに十分なほど勇敢ではなかったので、2番目の部分が含まれています。 :-) –

+0

'read_nonblock(4096)'は、ruby 1.9.3,2.0.0、および2.1.3では1行を返さないことを確認しました。この提案をうまく活用してください。 'ruby19 -e 'x = IO.popen(" cat/etc/fstab ")で検証するのに十分簡単です。睡眠0.2; p x.read_nonblock(4096) '' – chutz