2012-03-21 65 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