diff --git a/doc/io_streams.rdoc b/doc/io_streams.rdoc index 680d5e99c4..3ee8592687 100644 --- a/doc/io_streams.rdoc +++ b/doc/io_streams.rdoc @@ -87,31 +87,28 @@ Many examples here use these variables: === Basic \IO -==== Reading and Writing +You can perform basic stream \IO with these methods: -===== \Method #read +- IO#read: Returns all remaining or the next _n_ bytes read from the stream, + for a given _n_: -Returns all remaining or the next +n+ bytes read from the stream, for a given +n+: + f = File.new('t.txt') + f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n" + f.rewind + f.read(30) # => "First line\r\nSecond line\r\n\r\nFou" + f.read(30) # => "rth line\r\nFifth line\r\n" + f.read(30) # => nil + f.close - f = File.new('t.txt') - f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n" - f.rewind - f.read(30) # => "First line\r\nSecond line\r\n\r\nFou" - f.read(30) # => "rth line\r\nFifth line\r\n" - f.read(30) # => nil - f.close +- IO#write: Writes one or more given strings to the stream: -===== \Method #write + $stdout.write('Hello', ', ', 'World!', "\n") # => 14 + $stdout.write('foo', :bar, 2, "\n") -Writes one or more given strings to the stream: + Output: - $stdout.write('Hello', ', ', 'World!', "\n") # => 14 - $stdout.write('foo', :bar, 2, "\n") - -Output: - - Hello, World! - foobar2 + Hello, World! + foobar2 ==== Position @@ -120,112 +117,92 @@ which is the byte offset at which the next read or write is to occur. A new stream has position zero (and line number zero); method +rewind+ resets the position (and line number) to zero. -===== \Method #tell +The relevant methods: -Returns the current position (in bytes) in the stream: - - f = File.new('t.txt') - f.tell # => 0 - f.gets # => "First line\n" - f.tell # => 12 - f.close - -Aliased as pos. - -===== \Method #pos= - -Sets the position of the stream (in bytes): - - f = File.new('t.txt') - f.tell # => 0 - f.pos = 20 # => 20 - f.tell # => 20 - f.close - -===== \Method #seek - -Sets the position of the stream to a given integer +offset+ -(in bytes), with respect to a given constant +whence+, which is one of: - -- +:CUR+ or IO::SEEK_CUR: - Repositions the stream to its current position plus the given +offset+: +- IO#tell (aliased as +#pos+): + Returns the current position (in bytes) in the stream: f = File.new('t.txt') - f.tell # => 0 - f.seek(20, :CUR) # => 0 - f.tell # => 20 - f.seek(-10, :CUR) # => 0 - f.tell # => 10 + f.tell # => 0 + f.gets # => "First line\n" + f.tell # => 12 f.close -- +:END+ or IO::SEEK_END: - Repositions the stream to its end plus the given +offset+: +- IO#pos=: Sets the position of the stream (in bytes): f = File.new('t.txt') - f.tell # => 0 - f.seek(0, :END) # => 0 # Repositions to stream end. - f.tell # => 52 - f.seek(-20, :END) # => 0 - f.tell # => 32 - f.seek(-40, :END) # => 0 - f.tell # => 12 + f.tell # => 0 + f.pos = 20 # => 20 + f.tell # => 20 f.close -- +:SET+ or IO:SEEK_SET: - Repositions the stream to the given +offset+: +- IO#seek: Sets the position of the stream to a given integer +offset+ + (in bytes), with respect to a given constant +whence+, which is one of: + + - +:CUR+ or IO::SEEK_CUR: + Repositions the stream to its current position plus the given +offset+: + + f = File.new('t.txt') + f.tell # => 0 + f.seek(20, :CUR) # => 0 + f.tell # => 20 + f.seek(-10, :CUR) # => 0 + f.tell # => 10 + f.close + + - +:END+ or IO::SEEK_END: + Repositions the stream to its end plus the given +offset+: + + f = File.new('t.txt') + f.tell # => 0 + f.seek(0, :END) # => 0 # Repositions to stream end. + f.tell # => 52 + f.seek(-20, :END) # => 0 + f.tell # => 32 + f.seek(-40, :END) # => 0 + f.tell # => 12 + f.close + + - +:SET+ or IO:SEEK_SET: + Repositions the stream to the given +offset+: + + f = File.new('t.txt') + f.tell # => 0 + f.seek(20, :SET) # => 0 + f.tell # => 20 + f.seek(40, :SET) # => 0 + f.tell # => 40 + f.close + +- IO#rewind: Positions the stream to the beginning (also resetting the line number): f = File.new('t.txt') - f.tell # => 0 - f.seek(20, :SET) # => 0 - f.tell # => 20 - f.seek(40, :SET) # => 0 - f.tell # => 40 + f.tell # => 0 + f.gets # => "First line\n" + f.tell # => 12 + f.rewind # => 0 + f.tell # => 0 + f.lineno # => 0 f.close -===== \Method #rewind - -Positions the stream to the beginning (also resetting the line number): - - f = File.new('t.txt') - f.tell # => 0 - f.gets # => "First line\n" - f.tell # => 12 - f.rewind # => 0 - f.tell # => 0 - f.lineno # => 0 - f.close - ==== Open and Closed Streams A new \IO stream may be open for reading, open for writing, or both. -===== \Method #close +You can close a stream using these methods: -Closes the stream for both reading and writing. +- IO#close: Closes the stream for both reading and writing. +- IO#close_read (not in \ARGF): Closes the stream for reading. +- IO#close_write (not in \ARGF): Closes the stream for writing. -===== \Method #close_read +You can query whether a stream is closed using this method: -Closes the stream for reading, - -Not in ARGF. - -===== \Method #close_write - -Closes the stream for writing - -Not in ARGF. - -===== \Method #closed? - -Returns whether the stream is closed. +- IO#closed?: Returns whether the stream is closed. ==== End-of-Stream -===== \Method #eof? - -Returns whether a stream is positioned at its end; aliased as +#eof+. - -===== Repositioning to End-of-Stream +You can query whether a stream is positioned at its end using +method IO#eof? (also aliased as +#eof+). You can reposition to end-of-stream by reading all stream content: @@ -243,65 +220,52 @@ Or by using method IO#seek: === Line \IO -You can process an \IO stream line-by-line. +You can read an \IO stream line-by-line using these methods: -===== \Method #each_line +- IO#each_line: Passes each line to the block: -Passes each line to the block: + f = File.new('t.txt') + f.each_line {|line| p line } - f = File.new('t.txt') - f.each_line {|line| p line } + Output: -Output: + "First line\n" + "Second line\n" + "\n" + "Fourth line\n" + "Fifth line\n" - "First line\n" - "Second line\n" - "\n" - "Fourth line\n" - "Fifth line\n" + The reading may begin mid-line: -The reading may begin mid-line: + f = File.new('t.txt') + f.pos = 27 + f.each_line {|line| p line } - f = File.new('t.txt') - f.pos = 27 - f.each_line {|line| p line } + Output: -Output: + "rth line\n" + "Fifth line\n" - "rth line\n" - "Fifth line\n" +- IO#gets (also in Kernel): Returns the next line (which may begin mid-line): -===== \Method #gets + f = File.new('t.txt') + f.gets # => "First line\n" + f.gets # => "Second line\n" + f.pos = 27 + f.gets # => "rth line\n" + f.readlines # => ["Fifth line\n"] + f.gets # => nil -Returns the next line (which may begin mid-line); also in Kernel: +- IO#readline (also in Kernel; not in StringIO): + Like #gets, but raises an exception at end-of-stream. - f = File.new('t.txt') - f.gets # => "First line\n" - f.gets # => "Second line\n" - f.pos = 27 - f.gets # => "rth line\n" - f.readlines # => ["Fifth line\n"] - f.gets # => nil +- IO#readlines (also in Kernel): Returns all remaining lines in an array; + may begin mid-line: -===== \Method #readline - -Like #gets, but raises an exception at end-of-stream. - -Also in Kernel; not in StringIO. - -===== \Method #readlines - -Returns all remaining lines in an array; -may begin mid-line: - - f = File.new('t.txt') - f.pos = 19 - f.readlines # => ["ine\n", "\n", "Fourth line\n", "Fifth line\n"] - f.readlines # => [] - -Also in Kernel. - -===== Optional Reader Arguments + f = File.new('t.txt') + f.pos = 19 + f.readlines # => ["ine\n", "\n", "Fourth line\n", "Fifth line\n"] + f.readlines # => [] Each of these reader methods may be called with: @@ -309,16 +273,14 @@ Each of these reader methods may be called with: - An optional line-size limit, +limit+. - Both +sep+ and +limit+. -===== \Method #puts +You can write to an \IO stream line-by-line using this method: -Writes objects to the stream: +- IO#puts (also in Kernel; not in \StringIO): Writes objects to the stream: - f = File.new('t.tmp', 'w') - f.puts('foo', :bar, 1, 2.0, Complex(3, 0)) - f.flush - File.read('t.tmp') # => "foo\nbar\n1\n2.0\n3+0i\n" - -Also in Kernel; not in StringIO. + f = File.new('t.tmp', 'w') + f.puts('foo', :bar, 1, 2.0, Complex(3, 0)) + f.flush + File.read('t.tmp') # => "foo\nbar\n1\n2.0\n3+0i\n" ==== Line Separator @@ -406,21 +368,13 @@ which is the non-negative integer line number in the stream where the next read will occur. The line number is the number of lines read by certain line-oriented methods -({::foreach}[rdoc-ref:IO.foreach], -{#each_line}[rdoc-ref:io_streams.rdoc@Method+-23each_line], -{#gets}[rdoc-ref:io_streams.rdoc@Method+-23gets], -{#readline}[rdoc-ref:io_streams.rdoc@Method+-23readline], -{#readlines}[rdoc-ref:io_streams.rdoc@Method+-23readlines]) +(IO.foreach, IO#each_line, IO#gets, IO#readline, and IO#readlines) according to the given (or default) line separator +sep+. A new stream is initially has line number zero (and position zero); method +rewind+ resets the line number (and position) to zero. -===== \Method #lineno - -Returns the line number. - -===== Changes to the Line Number +\Method IO#lineno returns the line number. Reading lines from a stream usually changes its line number: @@ -460,128 +414,102 @@ that determine how lines in a stream are to be treated: === Character \IO -You can process an \IO stream character-by-character. +You can process an \IO stream character-by-character using these methods: -===== \Method #getc +- IO#getc: Reads and returns the next character from the stream: -Reads and returns the next character from the stream: + f = File.new('t.rus') + f.getc # => "т" + f.getc # => "е" + f.getc # => "с" + f.getc # => "т" + f.getc # => nil - f = File.new('t.rus') - f.getc # => "т" - f.getc # => "е" - f.getc # => "с" - f.getc # => "т" - f.getc # => nil +- IO#readchar (not in \StringIO): + Like #getc, but raises an exception at end-of-stream: -===== \Method #readchar + f.readchar # Raises EOFError. -Like #getc, but raises an exception at end-of-stream. +- IO#ungetc (not in \ARGF): + Pushes back ("unshifts") a character or integer onto the stream: -Not in \StringIO. + path = 't.tmp' + File.write(path, 'foo') + File.open(path) do |f| + f.ungetc('т') + f.read # => "тfoo" + end -===== \Method #ungetc +- IO#putc (also in Kernel): Writes a character to the stream: -Pushes back ("unshifts") a character or integer onto the stream: + File.open('t.tmp', 'w') do |f| + f.putc('т') + f.putc('е') + f.putc('с') + f.putc('т') + end + File.read('t.tmp') # => "тест" - path = 't.tmp' - File.write(path, 'foo') - File.open(path) do |f| - f.ungetc('т') - f.read # => "тfoo" - end +- IO#each_char: Reads each remaining character in the stream, + passing the character to the given block: -Not in \ARGF. + File.open('t.rus') do |f| + f.pos = 4 + f.each_char {|c| p c } + end -===== \Method #putc + Output: -Writes a character to the stream: - - File.open('t.tmp', 'w') do |f| - f.putc('т') - f.putc('е') - f.putc('с') - f.putc('т') - end - File.read('t.tmp') # => "тест" - -Also in Kernel. - -===== \Method #each_char - -Reads each remaining character in the stream, -passing the character to the given block: - - File.open('t.rus') do |f| - f.pos = 4 - f.each_char {|c| p c } - end - -Output: - - "с" - "т" + "с" + "т" === Byte \IO -You can process an \IO stream byte-by-byte. +You can process an \IO stream byte-by-byte using these methods: -===== \Method #getbyte +- IO#getbyte: Returns the next 8-bit byte as an integer in range 0..255: -Returns the next 8-bit byte as an integer in range 0..255: + File.read('t.dat') + # => "\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94" + File.read('t.dat') + # => "\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94" + f = File.new('t.dat') + f.getbyte # => 254 + f.getbyte # => 255 + f.seek(-2, :END) + f.getbyte # => 153 + f.getbyte # => 148 + f.getbyte # => nil - File.read('t.dat') - # => "\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94" - File.read('t.dat') - # => "\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94" - f = File.new('t.dat') - f.getbyte # => 254 - f.getbyte # => 255 - f.seek(-2, :END) - f.getbyte # => 153 - f.getbyte # => 148 - f.getbyte # => nil +- IO#readbyte (not in \StringIO): + Like #getbyte, but raises an exception if at end-of-stream: -===== \Method #readbyte + f.readbyte # Raises EOFError. -Like #getbyte, but raises an exception if at end-of-stream: +- IO#ungetbyte (not in \ARGF): + Pushes back ("unshifts") a byte back onto the stream: - f.readbyte # Raises EOFError. + f.ungetbyte(0) + f.ungetbyte(01) + f.read # => "\u0001\u0000" -Not in \StringIO. +- IO#each_byte: Reads each remaining byte in the stream, + passing the byte to the given block: -===== \Method #ungetbyte + f.seek(-4, :END) + f.each_byte {|b| p b } -Pushes back ("unshifts") a byte back onto the stream: + Output: - f.ungetbyte(0) - f.ungetbyte(01) - f.read # => "\u0001\u0000" - -Not in \ARGF. - -===== \Method #each_byte - -Reads each remaining byte in the stream, -passing the byte to the given block: - - f.seek(-4, :END) - f.each_byte {|b| p b } - -Output: - - 153 - 147 - 153 - 148 + 153 + 147 + 153 + 148 === Codepoint \IO -You can process an \IO stream codepoint-by-codepoint. - -===== \Method +each_codepoint+ - -Reads each remaining codepoint in the stream, -passing the codepoint to the given block: +You can process an \IO stream codepoint-by-codepoint using method ++#each_codepoint+: a = [] File.open('t.rus') do |f|