2012-03-21 18 views
7

Sto provando a leggere una riga da un io in modo non bloccante.ruby ​​linea non bloccante read

Sfortunatamente readline blocchi. Penso di poterlo risolvere con read_nonblock con un buffer aggiuntivo dove immagazzino il risultato parziale, controllo se ci sono più righe nel buffer, ecc. Ma sembra un po 'complicato per un compito semplice come questo. C'è un modo migliore per farlo?

Nota: sto usando demultiplexing evento (select) e sono abbastanza soddisfatto, non voglio creare discussioni, utilizzare EventMachine, ecc ...

risposta

5

Penso che la soluzione è read_nonblock probabilmente la strada da percorrere. Semplice, non è al massimo efficiente versione scimmia-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  

Questo genera un'eccezione se non ci sono dati pronti, proprio come read_nonblock, in modo da avere di salvataggio per ottenere solo un pari a zero indietro, ecc

+0

Sì, quella era la mia idea originale, ed è quello che ho finalmente fatto, ma ho letto tanto come posso (non solo un singolo carattere), penso che sia meglio per le prestazioni. Grazie per il suggerimento monke-patch;) –

3

questa implementazione migliora la risposta di Mark Reed da non scartare lettura dei dati che non si esaurisce in una nuova riga:

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

"nessuna garanzia" - è piuttosto spaventoso. non fare affidamento su "funzionalità" non documentate. "Ho provato questo" - rigorosamente? con diversi metodi di input? Potrebbe funzionare solo perché il tuo input era a buffer di linea ... –

+0

Non ero abbastanza coraggioso da poter contare su di esso, ed è per questo che ho incluso la seconda parte. :-) –

+0

Ho verificato che 'read_nonblock (4096)' non restituisce una singola riga su Ruby 1.9.3, 2.0.0 e 2.1.3. Meglio prendere questo suggerimento. Abbastanza facile da verificare con 'ruby19 -e 'x = IO.popen (" cat/etc/fstab "); dormire 0,2; p x.read_nonblock (4096) ''. – chutz