2012-03-21 15 views
7

Estoy tratando de leer una línea de una io de forma no bloqueante.ruby ​​línea no bloqueante leer

Desafortunadamente readline bloques. Creo que puedo resolver esto con read_nonblock con un búfer adicional donde guardo el resultado parcial, verifico si hay varias líneas en el búfer, etc. pero parece un poco complicado para una tarea simple como esta. ¿Hay una mejor manera de hacer esto?

Nota: Estoy usando demultiplexación evento (select) y estoy muy contento con él, no quiero crear enlaces, use EventMachine, etc ...

Respuesta

5

Creo que la solución es read_nonblock probablemente el camino a seguir. Simple, no de máxima eficiencia versión mono-patch:

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  

Eso genera una excepción si no hay datos listos, al igual que read_nonblock, así que hay que rescatar que para obtener sólo una nula espalda, etc.

+0

Sí, esa fue mi idea original, y eso es lo que finalmente hice, pero he leído tanto como pueda (no solo un char), creo que es mejor para el rendimiento. Gracias por la punta de parche de monje;) –

3

esta aplicación mejora en la respuesta de Mark Reed al no descartar lectura de datos que no termina en una nueva línea:

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

"sin garantía": eso da un poco de miedo. no confíe en 'características' no documentadas. "Probé esto" - ¿por qué? con diferentes métodos de entrada? Puede que solo haya funcionado porque tu entrada fue almacenada en línea ... –

+0

No fui lo suficientemente valiente como para confiar tampoco, por lo que incluí la segunda parte. :-) –

+0

Comprobé que 'read_nonblock (4096)' no devuelve una sola línea en ruby ​​1.9.3, 2.0.0 y 2.1.3. Mejor saca esta sugerencia. Lo suficientemente fácil de verificar con 'ruby19 -e 'x = IO.popen (" cat/etc/fstab "); dormir 0.2; p x.read_nonblock (4096) ''. – chutz

Cuestiones relacionadas