Programming Ruby: The Pragmatic Programmer's Guide

# Programming Ruby ### The Pragmatic Programmer's Guide
Previous < | Contents ^ | Next >

class IO |
Parent: | Object
Version: | 1.6

### Index:

foreach new pipe popen readlines select << binmode clone close close_read close_write closed? each each_byte each_line eof eof? fcntl fileno flush getc gets ioctl isatty lineno lineno= pid pos pos= print printf putc puts read readchar readline readlines reopen rewind seek stat sync sync= sysread syswrite tell to_i to_io tty? ungetc write

Subclasses: File

Class `IO` is the basis for all input and output in Ruby. An I/O stream may be duplexed (that is, bidirectional), and so may use more than one native operating system stream.

Many of the examples in this section use class `File`, the only standard subclass of `IO`. The two classes are closely associated.

As used in this section, aPortname may take any of the following forms.

- A plain string represents a filename suitable for the underlying operating system.
- A string starting with ```|`'' indicates a subprocess. The remainder of the string following the ```|`'' is invoked as a process with appropriate input/output channels connected to it.
- A string equal to ```|-`'' will create another Ruby instance as a subprocess.

Ruby will convert pathnames between different operating system conventions if possible. For instance, on a Windows system the filename ```/gumby/ruby/test.rb`'' will be opened as ```\gumby\ruby\test.rb`''. When specifying a Windows-style filename in a Ruby string, remember to escape the backslashes:

    "c:\\gumby\\ruby\\test.rb"

Our examples here will use the Unix-style forward slashes; `File::SEPARATOR` can be used to get the platform-specific separator character.

I/O ports may be opened in any one of several different modes, which are shown in this section as aModeString. This mode string must be one of the values listed in Table 22.5 on page 326.

Mode strings
Mode | Meaning
``r'' | Read-only, starts at beginning of file (default mode).
``r+'' | Read-write, starts at beginning of file.
``w'' | Write-only, truncates existing file to zero length or creates a new file for writing.
``w+'' | Read-write, truncates existing file to zero length or creates a new file for reading and writing.
``a'' | Write-only, starts at end of file if file exists, otherwise creates a new file for writing.
``a+'' | Read-write, starts at end of file if file exists, otherwise creates a new file for reading and writing.
``b'' | (DOS/Windows only) Binary file mode (may appear with any of the key letters listed above).

mixins
Enumerable: | collect, detect, each_with_index, entries, find, find_all, grep, include?, map, max, member?, min, reject, select, sort, to_a

class methods
foreach | IO.foreach( aPortName, aSepString=`$/` ) {| line | block } -> `nil`
|  | Executes the block for every line in the named I/O port, where lines are separated by aSepString.
    IO.foreach("testfile") {|x| print "GOT ", x }
produces:
    GOT This is line one
    GOT This is line two
    GOT This is line three
    GOT And so on...
new | IO.new( anInteger, aModeString ) -> aFile
|  | Returns a new `File` object (a stream) for the given integer file descriptor and mode string. See also `IO#fileno` .
    a = IO.new(2,"w")      # '2' is standard error
    $stderr.puts "Hello"
    a.puts "World"
produces:
    Hello
    World
pipe | IO.pipe -> anArray
|  | Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element array of `IO` objects: `[` readFile, writeFile `]`. Not available on all platforms. In the example below, the two processes close the ends of the pipe that they are not using. This is not just a cosmetic nicety. The read end of a pipe will not generate an end of file condition if there are any writers with the pipe still open. In the case of the parent process, the `rd.read` will never return if it does not first issue a `wr.close`.

    rd, wr = IO.pipe

    if fork
      wr.close
      puts "Parent got: <#{rd.read}>"
      rd.close
      Process.wait
    else
      rd.close
      puts "Sending message to parent"
      wr.write "Hi Dad"
      wr.close
    end
produces:
    Sending message to parent
    Parent got: <Hi Dad>
popen | IO.popen( aCmdString, aModeString="r" ) -> anIO IO.popen( aCmdString, aModeString="r" ) {| anIO | block } -> `nil`
|  | Runs the specified command string as a subprocess; the subprocess's standard input and output will be connected to the returned `IO` object. If aCmdString starts with a ```-`'', then a new instance of Ruby is started as the subprocess. The default mode for the new file object is ``r'', but aModeString may be set to any of the modes in Table 22.5 on page 326. If a block is given, Ruby will run the command as a child connected to Ruby with a pipe. Ruby's end of the pipe will be passed as a parameter to the block. If a block is given with a aCmdString of ```-`'', the block will be run in two separate processes: once in the parent, and once in a child. The parent process will be passed the pipe object as a parameter to the block, the child version of the block will be passed `nil`, and the child's standard in and standard out will be connected to the parent through the pipe. Not available on all platforms.
    f = IO.popen("uname")
    p f.readlines
    puts "Parent is #{Process.pid}"
    IO.popen ("date") { |f| puts f.gets }
    IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f}"}
produces:
    ["Linux\n"]
    Parent is 561
    Sun Jun  9 00:17:46 CDT 2002
    564 is here, f is
    561 is here, f is #<IO:0x401b54dc>
readlines | IO.readlines( aPortName, aSepString=`$/` ) -> anArray
|  | Reads the entire file specified by aPortName as individual lines, and returns those lines in an array. Lines are separated by aSepString.
`a = IO.readlines("testfile")`
`a[0]` | » | `"This is line one\n"`
select | IO.select( readArray [, writeArray [ errorArray [ timeout ] ] ] ) -> anArray or `nil`
|  | See `Kernel#select` on page 422.

instance methods
<< | ios << anObject -> ios
|  | String Output---Writes anObject to ios. anObject will be converted to a string using `to_s`.
    $stdout << "Hello " << "world!\n"
produces:
    Hello world!
binmode | ios.binmode -> ios
|  | Puts ios into binary mode. This is useful only in MS-DOS/Windows environments. Once a stream is in binary mode, it cannot be reset to nonbinary mode.
clone | ios.clone -> anIO
|  | Creates a new I/O stream, copying all the attributes of ios. The file position is shared as well, so reading from the clone will alter the file position of the original, and vice-versa.
close | ios.close -> `nil`
|  | Closes ios and flushes any pending writes to the operating system. The stream is unavailable for any further data operations; an `IOError` is raised if such an attempt is made. I/O streams are automatically closed when they are claimed by the garbage collector.
close_read | ios.close_read -> `nil`
|  | Closes the read end of a duplex I/O stream (i.e., one that contains both a read and a write stream, such as a pipe). Will raise an `IOError` if the stream is not duplexed.
    f = IO.popen("/bin/sh","r+")
    f.close_read
    f.readlines
produces:
    prog.rb:3:in `readlines': not opened for reading (IOError)
    	from prog.rb:3
close_write | ios.close_write -> `nil`
|  | Closes the write end of a duplex I/O stream (i.e., one that contains both a read and a write stream, such as a pipe). Will raise an `IOError` if the stream is not duplexed.
    f = IO.popen("/bin/sh","r+")
    f.close_write
    f.print "nowhere"
produces:
    prog.rb:3:in `write': not opened for writing (IOError)
    	from prog.rb:3:in `print'
    	from prog.rb:3
closed? | ios.closed? -> `true` or `false`
|  | Returns `true` if ios is completely closed (for duplex streams, both reader and writer), `false` otherwise.
`f = File.new("testfile")`
`f.close` | » | `nil`
`f.closed?` | » | `true`
`f = IO.popen("/bin/sh","r+")`
`f.close_write` | » | `nil`
`f.closed?` | » | `false`
`f.close_read` | » | `nil`
`f.closed?` | » | `true`
each | ios.each( aSepString=`$/` ) {| line | block } -> ios
|  | Executes the block for every line in ios, where lines are separated by aSepString. ios must be opened for reading or an `IOerror` will be raised.
    f = File.new("testfile")
    f.each {|line| puts "#{f.lineno}: #{line}" }
produces:
    1: This is line one
    2: This is line two
    3: This is line three
    4: And so on...
each_byte | ios.each_byte {| byte | block } -> `nil`
|  | Calls the given block once for each byte (0..255) in ios, passing the byte as an argument. The stream must be opened for reading or an `IOerror` will be raised.
`f = File.new("testfile")`
`checksum = 0`
`f.each_byte {|x| checksum ^= x }` | » | `#<File:0x401b5cac>`
`checksum` | » | `12`
each_line | ios.each_line( aSepString=`$/` ) {| line | block } -> ios
|  | Synonym for `IO#each` .
eof | ios.eof -> `true` or `false`
|  | Returns true if ios is at end of file. The stream must be opened for reading or an `IOError` will be raised.
`f = File.new("testfile")`
`dummy = f.readlines`
`f.eof` | » | `true`
eof? | ios.eof? -> `true` or `false`
|  | Synonym for `IO#eof` .
fcntl | ios.fcntl( anIntegerCmd, anArg ) -> anInteger
|  | Provides a mechanism for issuing low-level commands to control or query file-oriented I/O streams. Arguments and results are platform dependent. If anArg is a number, its value is passed directly. If it is a string, it is interpreted as a binary sequence of bytes. On Unix platforms, see `fcntl(2)` for details. Not implemented on all platforms.
fileno | ios.fileno -> aFixnum
|  | Returns an integer representing the numeric file descriptor for ios.
`$stdin.fileno` | » | `0`
`$stdout.fileno` | » | `1`
flush | ios.flush -> ios
|  | Flushes any buffered data within ios to the underlying operating system (note that this is Ruby internal buffering only; the OS may buffer the data as well).
    $stdout.print "no newline"
    $stdout.flush
produces:
    no newline
getc | ios.getc -> aFixnum or `nil`
|  | Gets the next 8-bit byte (0..255) from ios. Returns `nil` if called at end of file.
`f = File.new("testfile")`
`f.getc` | » | `84`
`f.getc` | » | `104`
gets | ios.gets( aSepString=`$/` ) -> aString or `nil`
|  | Reads the next ``line'' from the I/O stream; lines are separated by aSepString. A separator of `nil` reads the entire contents, and a zero-length separator reads the input a paragraph at a time (two successive newlines in the input separate paragraphs). The stream must be opened for reading or an `IOerror` will be raised. The line read in will be returned and also assigned to `$_`. Returns `nil` if called at end of file.
`File.new("testfile").gets` | » | `"This is line one\n"`
`$_` | » | `"This is line one\n"`
ioctl | ios.ioctl( anIntegerCmd, anArg ) -> anInteger
|  | Provides a mechanism for issuing low-level commands to control or query I/O devices. Arguments and results are platform dependent. If anArg is a number, its value is passed directly. If it is a string, it is interpreted as a binary sequence of bytes. On Unix platforms, see `ioctl(2)` for details. Not implemented on all platforms.
isatty | ios.isatty -> `true` or `false`
|  | Returns `true` if ios is associated with a terminal device (tty), `false` otherwise.
`File.new("testfile").isatty` | » | `false`
`File.new("/dev/tty").isatty` | » | `true`
lineno | ios.lineno -> anInteger
|  | Returns the current line number in ios. The stream must be opened for reading. `lineno` counts the number of times `gets` is called, rather than the number of newlines encountered. The two values will differ if `gets` is called with a separator other than newline. See also the `$.` variable.
`f = File.new("testfile")`
`f.lineno` | » | `0`
`f.gets` | » | `"This is line one\n"`
`f.lineno` | » | `1`
`f.gets` | » | `"This is line two\n"`
`f.lineno` | » | `2`
lineno= | ios.lineno = anInteger -> anInteger
|  | Manually sets the current line number to the given value. `$.` is updated only on the next read.
`f = File.new("testfile")`
`f.gets` | » | `"This is line one\n"`
`$.` | » | `1`
`f.lineno = 1000`
`f.lineno` | » | `1000`
`$. # lineno of last read` | » | `1`
`f.gets` | » | `"This is line two\n"`
`$. # lineno of last read` | » | `1001`
pid | ios.pid -> aFixnum
|  | Returns the process ID of a child process associated with ios. This will be set by `IO.popen` .
    pipe = IO.popen("-")
    if pipe
      $stderr.puts "In parent, child pid is #{pipe.pid}"
    else
      $stderr.puts "In child, pid is #{$$}"
    end
produces:

    In parent, child pid is 600In child, pid is 600
pos | ios.pos -> anInteger
|  | Returns the current offset (in bytes) of ios.
`f = File.new("testfile")`
`f.pos` | » | `0`
`f.gets` | » | `"This is line one\n"`
`f.pos` | » | `17`
pos= | ios.pos = anInteger -> 0
|  | Seeks to the given position (in bytes) in ios.
`f = File.new("testfile")`
`f.pos = 17`
`f.gets` | » | `"This is line two\n"`
print | ios.print( [ anObject=`$_` ]* ) -> `nil`
|  | Writes the given object(s) to ios. The stream must be opened for writing. If the output record separator (`$\`) is not `nil`, it will be appended to the output. If no arguments are given, prints `$_`. Objects that aren't strings will be converted by calling their `to_s` method. Returns `nil`.
    $stdout.print("This is ", 100, " percent.\n")
produces:
    This is 100 percent.
printf | ios.printf( aFormatString [, anObject ]* ) -> `nil`
|  | Formats and writes to ios, converting parameters under control of the format string. See `Kernel#sprintf` on page 423 for details.
putc | ios.putc( anObject ) -> anObject
|  | Writes the given character (taken from a `String` or a `Fixnum`) on ios.
    $stdout.putc "A"
    $stdout.putc 65
produces:
    AA
puts | ios.puts( [ anObject ]* ) -> `nil`
|  | Writes the given objects to ios as with `IO#print` . Writes a record separator (typically a newline) after any that do not already end with a newline sequence. If called with an array argument, writes each element on a new line. If called without arguments, outputs a single record separator.
    $stdout.puts("this", "is", "a", "test")
produces:
    this
    is
    a
    test
read | ios.read( [ anInteger ] ) -> aString or `nil`
|  | Reads at most anInteger bytes from the I/O stream, or to the end of file if anInteger is omitted. Returns `nil` if called at end of file.
`f = File.new("testfile")`
`f.read(16)` | » | `"This is line one"`
readchar | ios.readchar -> aFixnum
|  | Reads a character as with `IO#getc` , but raises an `EOFError` on end of file.
readline | ios.readline( aSepString=`$/` ) -> aString
|  | Reads a line as with `IO#gets` , but raises an `EOFError` on end of file.
readlines | ios.readlines( aSepString=`$/` ) -> anArray
|  | Reads all of the lines in ios, and returns them in anArray. Lines are separated by the optional aSepString. The stream must be opened for reading or an `IOerror` will be raised.
`f = File.new("testfile")`
`f.readlines[0]` | » | `"This is line one\n"`
reopen | ios.reopen( anOtherIO ) -> ios ios.reopen( aPath, aModeStr ) -> ios
|  | Reassociates ios with the I/O stream given in anOtherIO or to a new stream opened on aPath. This may dynamically change the actual class of this stream.
`f1 = File.new("testfile")`
`f2 = File.new("testfile")`
`f2.readlines[0]` | » | `"This is line one\n"`
`f2.reopen(f1)` | » | `#<File:0x401b5a54>`
`f2.readlines[0]` | » | `"This is line one\n"`
rewind | ios.rewind -> 0
|  | Positions ios to the beginning of input, resetting `lineno` to zero.
`f = File.new("testfile")`
`f.readline` | » | `"This is line one\n"`
`f.rewind` | » | `0`
`f.lineno` | » | `0`
`f.readline` | » | `"This is line one\n"`
seek | ios.seek( anInteger, whence=`SEEK_SET` ) -> 0
|  | Seeks to a given offset anInteger in the stream according to the value of whence:

`IO::SEEK_CUR` | Seeks to anInteger plus current position.
`IO::SEEK_END` | Seeks to anInteger plus end of stream (you probably want a negative value for anInteger).
`IO::SEEK_SET` | Seeks to the absolute location given by anInteger.
`f = File.new("testfile")`
`f.seek(-13, IO::SEEK_END)` | » | `0`
`f.readline` | » | `"And so on...\n"`
stat | ios.stat -> aStat
|  | Returns status information for ios as an object of type `File::Stat`.
`f = File.new("testfile")`
`s = f.stat`
`"%o" % s.mode` | » | `"100644"`
`s.blksize` | » | `4096`
`s.atime` | » | `Sun Jun 09 00:17:48 CDT 2002`
sync | ios.sync -> `true` or `false`
|  | Returns the current ``sync mode'' of ios. When sync mode is true, all output is immediately flushed to the underlying operating system and is not buffered by Ruby internally.
`f = File.new("testfile")`
`f.sync` | » | `false`
sync= | ios.sync = aBoolean -> aBoolean
|  | Sets the ``sync mode'' to `true` or `false`. When sync mode is true, all output is immediately flushed to the underlying operating system and is not buffered internally. Returns the new state.
    f = File.new("testfile")
    f.sync = true
sysread | ios.sysread( anInteger ) -> aString
|  | Reads anInteger bytes from ios using a low-level read and returns them as a string. Do not mix with other methods that read from ios or you may get unpredictable results. Raises `SystemCallError` on error and `EOFError` at end of file.
`f = File.new("testfile")`
`f.sysread(16)` | » | `"This is line one"`
syswrite | ios.syswrite( aString ) -> anInteger
|  | Writes the given string to ios using a low-level write. Returns the number of bytes written. Do not mix with other methods that write to ios or you may get unpredictable results. Raises `SystemCallError` on error.
`f = File.new("out", "w")`
`f.syswrite("ABCDEF")` | » | `6`
tell | ios.tell -> anInteger
|  | Synonym for `IO#pos` .
to_i | ios.to_i -> anInteger
|  | Synonym for `IO#fileno` .
to_io | ios.to_io -> ios
|  | Returns ios.
tty? | ios.tty? -> `true` or `false`
|  | Synonym for `IO#isatty` .
ungetc | ios.ungetc( anInteger ) -> `nil`
|  | Pushes back one character onto ios, such that a subsequent buffered read will return it. Only one character may be pushed back before a subsequent read operation (that is, you will be able to read only the last of several characters that have been pushed back). Has no effect with unbuffered reads (such as `IO#sysread` ).
`f = File.new("testfile")` | » | `#<File:0x401b5b80>`
`c = f.getc` | » | `84`
`f.ungetc(c)` | » | `nil`
`f.getc` | » | `84`
write | ios.write( aString ) -> anInteger
|  | Writes the given string to ios. The stream must be opened for writing. If the argument is not a string, it will be converted to a string using `to_s`. Returns the number of bytes written.
    count = $stdout.write( "This is a test\n" )
    puts "That was #{count} bytes of data"
produces:
    This is a test
    That was 15 bytes of data

Previous < | Contents ^ | Next >

Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Copyright © 2001 by Addison Wesley Longman, Inc. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/)).

Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.

Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.