2009-05-31 6 views
13

Ich bin auf der Suche nach einer Methode in Ruby, die dies im Grunde ist:Gibt es eine einfache Methode, um zu überprüfen, ob eine Ruby IO-Instanz bei read() blockiert?

io.ready_for_read? 

Ich will nur, ob ein gegebenes IO Objekt (in meinem Fall das Ergebnis einer popen Call) hat Ausgang zur Verfügung, das heißt ein Folgeaufruf io.read(1) wird nicht blockiert.

Dies sind die zwei Optionen, die ich sehen, von denen keines Ich mag:

  1. io.read_nonblock - zu dünn eine Abstraktion von Unix read() - ich will nicht mit errno Fehlerbehandlung behandeln.

  2. io.select mit Timeout 0 - verschleiert den Zweck dieser einfachen Operation.

Gibt es eine bessere Alternative, die ich übersehen habe?

+0

Ich nicht/denke/so. Das ist wirklich was Select ist für. Ja, Select hat eine schreckliche Syntax, aber theoretisch könnte man ein "ready_for_read?" Geben Sie method in IO ein, das select verwendet. –

+0

Diese 'IO # ready_for_read?' Implementierung funktioniert nicht für mich - es gibt immer True zurück. Ich denke, das Problem ist, dass "IO # select" blockiert, bis der Stream zum Schreiben durch einen anderen Prozess geöffnet wird (was in meinem Fall immer schon der Fall ist), nicht bis tatsächlich Daten gelesen werden.Ich versuche, einen anderen Weg zu finden, um das zu erreichen, aber ich habe nicht viel Glück. –

Antwort

7

Ein bisschen spät, aber wenn Sie require 'io/wait', können Sie ready? verwenden, um sicherzustellen, dass die IO ohne Blockierung gelesen werden. Zugegeben, je nachdem, wie viel Sie beabsichtigen zu lesen (und wie Sie es vorhaben), blockiert Ihr IO-Objekt möglicherweise noch, aber das sollte helfen. Ich bin nicht sicher, ob diese Bibliothek auf allen Plattformen unterstützt wird, und ich weiß auch nicht, warum diese Funktionalität vom Rest der E/A-Bibliothek getrennt wurde. Sehen Sie mehr hier: http://ruby-doc.org/stdlib/libdoc/io/wait/rdoc/

6

Ich bin bereit, zu dem Schluss zu kommen, dass es keine einfache Methode gibt, dies zu tun. hier pro Vorschlag Peter Cooper, ist IO#ready_for_read?:

class IO 
    def ready_for_read? 
    result = IO.select([self], nil, nil, 0) 
    result && (result.first.first == self) 
    end 
end 
0

Unter Windows habe ich einige Inkonsistenzen mit IO/Warte gesehen. Der Rubin habe ich hier jetzt ist:

Rubin 1.9.2p136 (2010-12-25) [i386-mingw32]

Auf diese beiden NREAD und bereit? sind implementiert, aber sie liefern fehlerhafte Ergebnisse. Auf einer anderen Version, die ich verwendete bereit? war immer noch gebrochen und nadeln gab es nicht einmal.

Eine Möglichkeit ist die Verwendung von io.stat.size, die Ihnen die Anzahl der Bytes angibt, die in einem IO-Stream gelesen werden können.

Die Dokumentation schlägt vor, dass es für Dateien ist, aber ich habe es für Pipes verwendet, die mit einem separaten Prozess verbunden sind (über Ruby's Open3.popen3). Es hat für mich bisher funktioniert.

+0

Keine Wiederholung für STDIN. Es liest Null, obwohl definitiv Daten zu lesen sind. –

Verwandte Themen