2012-03-21 93 views
7

我試圖以非阻塞的方式從io讀取一行。紅寶石非阻塞行讀取

不幸的是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,所以你要救的是隻得到一個零背部等

+0

是啊,那是我最初的想法,而這正是我終於做到了,但我看像我可以(不只是一個字符),我認爲這對性能更好。感謝monke-patch提示;) – 2012-09-21 15:39:29

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

「不保證」 - 這有點嚇人。不要依賴不確定的「特徵」。 「我測試了這個」 - 真的嗎?用不同的輸入法?它可能只工作,因爲你的輸入是行緩衝... – 2014-01-02 17:26:18

+0

我還沒有足夠的勇氣來依靠它,這就是爲什麼我包括第二部分。 :-) – 2014-01-02 21:09:20

+0

我驗證了'read_nonblock(4096)'在ruby 1.9.3,2.0.0和2.1.3上沒有返回單行。最好把這個建議拿出來。很容易用'ruby19 -e'x = IO.popen(「cat/etc/fstab」)來驗證;睡覺0.2; p x.read_nonblock(4096)''。 – chutz 2014-10-06 13:47:53