14

I'm looking for a method in Ruby which is basically this:

io.ready_for_read?

I just want to check whether a given IO object (in my case, the result of a popen call) has output available, i.e. a follow up call io.read(1) will not block.

These are the two options I see, neither of which I like:

  1. io.read_nonblock - too thin an abstraction of Unix read() -- I don't want to deal with errno error handling.

  2. io.select with timeout 0 -- obfuscates the purpose of this simple operation.

Is there a better alternative that I have overlooked?

Dhskjlkakdh
  • 11,341
  • 5
  • 22
  • 17
  • I don't /think/ so. This is really what select is for. Yes, select has horrible syntax, but I guess in theory you could monkeypatch a "ready_for_read?" type method into IO that uses select. – Peter Cooper May 31 '09 at 16:17
  • That `IO#ready_for_read?` implementation doesn't work for me - it always returns true. I think the problem is that `IO#select` blocks until the stream is opened for writing by another process (which in my case it always already is), not until there is actual data to be read. I'm trying to track down another way to achieve this but I'm not having much luck. – ben_h Aug 28 '09 at 13:51

3 Answers3

9

A bit late, but if you require 'io/wait', you can use ready? to verify that the IO can be read without blocking. Granted, depending upon how much you intend on reading (and how you plan to do it) your IO object may still block, but this should help. I'm not sure if this library is supported on all platforms, and I also don't know why this functionality was separated from the rest of the IO library. See more here: http://ruby-doc.org/stdlib/libdoc/io/wait/rdoc/

Ian Eccles
  • 7,297
  • 1
  • 17
  • 20
6

I'm ready to conclude that no, there is no simple method to do this. Per Peter Cooper's suggestion, here is IO#ready_for_read?:

class IO
  def ready_for_read?
    result = IO.select([self], nil, nil, 0)
    result && (result.first.first == self)
  end
end
Dhskjlkakdh
  • 11,341
  • 5
  • 22
  • 17
0

On Windows I've seen some inconsistencies with IO/wait. The ruby I have here right now is:

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

On this one both nread and ready? are implemented, but they return erroneous results. On a different version that I was using ready? was still broken and nread didn't even exist.

One possibility is to use io.stat.size, which tells you the number of bytes available to read in an IO stream. http://www.ruby-doc.org/core/classes/File/Stat.html

The documentation suggests that it's for files, but I've used it on pipes connected to a separate process (via Ruby's Open3.popen3). It's worked for me so far.

wandarkaf
  • 1,839
  • 20
  • 30
Joel
  • 1