File: tut_io.html

package info (click to toggle)
rubybook 0.2.1-1
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k, lenny, squeeze, wheezy
  • size: 4,248 kB
  • ctags: 1,042
  • sloc: xml: 60,486; makefile: 25
file content (378 lines) | stat: -rw-r--r-- 16,780 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
<html><title>Programming Ruby: The Pragmatic Programmer's Guide</title><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"><STYLE TYPE="text/css"><!--
       BODY    { margin-left: 1in;
                 width: 6in;
                 font-family: helvetica, arial, sans-serif;
               }
       H1      { color: #000080;
                 font-family: helvetica, arial, sans-serif;
                 font-size: 22pt;
                 margin-left: 0in
               }
       H2      { color: #000080;  font: bold x-large helvetica, sans-serif;
                 margin-left: 0in }
       H3      { color: #000080;  font: bold   large helvetica, sans-serif; }
       H4      { color: #000080;  font: italic large helvetica, sans-serif; }
       .ruby   { background: #fff0f0 }
       .header { color: white }
       .subheader { color: #ffdddd }
       .sidebar   { width: 6in }
       span.sans { font-family: helvetica, arial, sans-serif }
       -->
   </STYLE><table bgcolor="#a03030" cellpadding="3" border="0" cellspacing="0"><tr><td colspan="3"><table bgcolor="#902020" cellpadding="20"><tr><td><h1 class="header">Programming Ruby</h1><h3 class="subheader">The Pragmatic Programmer's Guide</h3></td></tr></table></td></tr><tr><td width="33%" align="left"><a class="subheader" href="tut_modules.html">Previous &lt;</a></td><td width="33%" align="center" valign="middle"><a class="subheader" href="index.html">Contents ^</a><br></td><td width="33%" align="right"><a class="subheader" href="tut_threads.html">Next ></a><br></td></tr></table></head><body bgcolor="white">
<!--
    Copyright (c) 2001 by Addison Wesley Longman.  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/).
-->
<h1>Basic Input and Output</h1><hr><br>
<P></P>
Ruby
provides what at first sight looks like two separate sets of I/O
routines.  The first is the simple interface---we've been using it
pretty much exclusively so far.
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
print&nbsp;"Enter&nbsp;your&nbsp;name:&nbsp;"
name&nbsp;=&nbsp;gets
</pre></td></tr></table>

<P></P>
There are a whole set of I/O-related methods implemented in the
<code>Kernel</code> module---<code>gets</code>, <code>open</code>, <code>print</code>,
<code>printf</code>, <code>putc</code>, <code>puts</code>, <code>readline</code>,
<code>readlines</code>, and <code>test</code>---that make it simple and
convenient to write straightforward Ruby programs. These methods
typically do I/O to standard input and standard output, which makes
them useful for writing filters. You'll find them documented starting
on page 415.   
<P></P>
The second way, which gives you a lot more control, is to use <code>IO</code>
objects.
<h2>What Is an IO Object?</h2>
<P></P>
Ruby defines a single base class, <code>IO</code>, to handle input and output.
This base class is subclassed by classes <code>File</code> and
<code>BasicSocket</code> to provide more specialized behavior, but the
principles are the same throughout. An <code>IO</code> object is a bidirectional
channel between a Ruby program and some external resource.<em>[For those
who just have to know the implementation details, this means that a
single <code>IO</code> object can sometimes be managing more than one operating
system file descriptor. For example, if you open a pair of pipes, a
single <code>IO</code> object contains both a read pipe and a write pipe.]</em>
There may be more to an <code>IO</code> object than meets the eye, but in the
end you still simply write to it and read from it.
<P></P>
In this chapter, we'll be concentrating on class <code>IO</code> and its most
commonly used subclass, class <code>File</code>. For more details on using the
socket classes for networking, see the section beginning on page 473.
<h2>Opening and Closing Files</h2>
<P></P>
As you might expect, you can create a new file object using
<a href="ref_c_file.html#new"><code>File::new</code></a>.
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
aFile&nbsp;=&nbsp;File.new("testfile",&nbsp;"r")
<P></P>
#&nbsp;...&nbsp;process&nbsp;the&nbsp;file
<P></P>
aFile.close
</pre></td></tr></table>

<P></P>
You can create a <code>File</code> object that is open for reading, writing, or
both, according to the mode string (here we opened ``<code>testfile</code>'' for
reading with an ``<code>r</code>'').  The full list of allowed modes appears
on page 331.  You can also optionally specify file
permissions when creating a file; see the description of
<a href="ref_c_file.html#new"><code>File::new</code></a> on page 308 for details.  After opening
the file, we can work with it, writing and/or reading data as needed.
Finally, as responsible software citizens, we close the file, ensuring
that all buffered data is written and that all related resources are
freed.
<P></P>
But here Ruby can make life a little bit easier for you. The method
<a href="ref_c_file.html#open"><code>File::open</code></a> also opens a file. In regular use, it behaves just
like <a href="ref_c_file.html#new"><code>File::new</code></a>.
However, if there's a block associated with the
call, <code>open</code> behaves differently. Instead of returning a new
<code>File</code> object, it invokes the block, passing the
newly opened <code>File</code> as a parameter. When the block exits, the file
is automatically closed.
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
File.open("testfile",&nbsp;"r")&nbsp;do&nbsp;|aFile|
<P></P>
#&nbsp;...&nbsp;process&nbsp;the&nbsp;file
<P></P>
end
</pre></td></tr></table>

<h2>Reading and Writing Files</h2>
<P></P>
The same methods that we've been using for ``simple'' I/O are available 
for all file objects. So, <code>gets</code> reads a line from standard
input, and <code>aFile.gets</code> reads a line from the file object
<code>aFile</code>.
<P></P>
However, I/O objects enjoy an additional set of access methods, 
all intended to make our lives easier.
<h3>Iterators for Reading</h3>
<P></P>
As well as using the usual loops to read data from an <code>IO</code> stream,
you can also use various Ruby iterators.  <a href="ref_c_io.html#each_byte"><code>IO#each_byte</code></a> invokes a
block with the next 8-bit byte from the <code>IO</code> object (in this case,
an object of type <code>File</code>).
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
aFile&nbsp;=&nbsp;File.new("testfile")
aFile.each_byte&nbsp;{|ch|&nbsp;putc&nbsp;ch;&nbsp;putc&nbsp;?.&nbsp;}
</pre></td></tr></table>

<em>produces:</em>
<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
T.h.i.s.&nbsp;.i.s.&nbsp;.l.i.n.e.&nbsp;.o.n.e.
.T.h.i.s.&nbsp;.i.s.&nbsp;.l.i.n.e.&nbsp;.t.w.o.
.T.h.i.s.&nbsp;.i.s.&nbsp;.l.i.n.e.&nbsp;.t.h.r.e.e.
.A.n.d.&nbsp;.s.o.&nbsp;.o.n.......
.
</pre></td></tr></table>

<P></P>
<a href="ref_c_io.html#each_line"><code>IO#each_line</code></a> calls the block with the next line from the file.
In the next example, we'll make the original newlines visible using
<a href="ref_c_string.html#dump"><code>String#dump</code></a>, so you can see that we're not cheating.
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
aFile.each_line&nbsp;{|line|&nbsp;puts&nbsp;"Got&nbsp;#{line.dump}"&nbsp;}
</pre></td></tr></table>

<em>produces:</em>
<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
Got&nbsp;"This&nbsp;is&nbsp;line&nbsp;one\n"
Got&nbsp;"This&nbsp;is&nbsp;line&nbsp;two\n"
Got&nbsp;"This&nbsp;is&nbsp;line&nbsp;three\n"
Got&nbsp;"And&nbsp;so&nbsp;on...\n"
</pre></td></tr></table>

<P></P>
You can pass <code>each_line</code> any sequence of characters as a line
separator, and it will break up the input accordingly, returning
the line ending at the end of each line of data. That's why you see
the ``<code>\n</code>'' characters in the output of the previous example.
In the next example, we'll use ``<code>e</code>'' as the line separator.
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
aFile.each_line("e")&nbsp;do&nbsp;|line|
&nbsp;&nbsp;puts&nbsp;"Got&nbsp;#{&nbsp;line.dump&nbsp;}"
end
</pre></td></tr></table>

<em>produces:</em>
<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
Got&nbsp;"This&nbsp;is&nbsp;line"
Got&nbsp;"&nbsp;one"
Got&nbsp;"\nThis&nbsp;is&nbsp;line"
Got&nbsp;"&nbsp;two\nThis&nbsp;is&nbsp;line"
Got&nbsp;"&nbsp;thre"
Got&nbsp;"e"
Got&nbsp;"\nAnd&nbsp;so&nbsp;on...\n"
</pre></td></tr></table>

<P></P>
If you combine the idea of an iterator with the auto-closing block
feature, you get <a href="ref_c_io.html#foreach"><code>IO::foreach</code></a>. This method takes the name of an
I/O source, opens it for reading, calls the iterator once for every
line in the file, and then closes the file automatically.
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
IO.foreach("testfile")&nbsp;{&nbsp;|line|&nbsp;puts&nbsp;line&nbsp;}
</pre></td></tr></table>

<em>produces:</em>
<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
This&nbsp;is&nbsp;line&nbsp;one
This&nbsp;is&nbsp;line&nbsp;two
This&nbsp;is&nbsp;line&nbsp;three
And&nbsp;so&nbsp;on...
</pre></td></tr></table>

<P></P>
Or, if you prefer, you can retrieve an entire file into an array of
lines:
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="500">
<tr>
<td colspan="3" valign="top"><code>arr&nbsp;=&nbsp;IO.readlines("testfile")</code></td>
</tr>
<tr>
  <td valign="top"><code>arr.length</code></td>
  <td valign="top"></td>
  <td valign="top"><code>4</code></td>
</tr>
<tr>
  <td valign="top"><code>arr[0]</code></td>
  <td valign="top"></td>
  <td valign="top"><code>"This&nbsp;is&nbsp;line&nbsp;one\n"</code></td>
</tr>
</table>
<P></P>

<P></P>
Don't forget that I/O is never certain in an uncertain
world---exceptions will be raised on most errors, and you should be
ready to catch them and take appropriate action.
<h3>Writing to Files</h3>
<P></P>
So far, we've been merrily calling <code>puts</code> and <code>print</code>,
passing in any old object and trusting that Ruby will do the right
thing (which, of course, it does). But what exactly <em>is</em> it doing?
<P></P>
The answer is pretty simple. With a couple of exceptions, every object 
you pass to <code>puts</code> and <code>print</code> is converted to a string
by calling that object's <code>to_s</code> method. If for some reason
the <code>to_s</code> method doesn't return a valid string, a string is
created containing the object's class name and id, something like
<code>&lt;ClassName:0x123456></code>.
<P></P>
The exceptions are simple, too. The <code>nil</code> object will print as the
string ``nil,'' and an array passed to <code>puts</code> will be written
as if each of its elements in turn were passed separately to
<code>puts</code>.
<P></P>
What if you want to write binary data and don't want Ruby messing
with it?
Well, normally you can simply use <a href="ref_c_io.html#print"><code>IO#print</code></a> and pass
in a string containing the bytes to be written. However, you can
get at the low-level input and output routines if you really
want---have a look at the documentation for <a href="ref_c_io.html#sysread"><code>IO#sysread</code></a> and
<a href="ref_c_io.html#syswrite"><code>IO#syswrite</code></a> on page 339.
<P></P>
And how do you get the binary data into a string in the first place?
The two common ways are to poke it in byte by byte or to use
<a href="ref_c_array.html#pack"><code>Array#pack</code></a>.
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="500">
<tr>
  <td valign="top"><code>str&nbsp;=&nbsp;""</code></td>
  <td valign="top"></td>
  <td valign="top"><code>""</code></td>
</tr>
<tr>
  <td valign="top"><code>str&nbsp;&lt;&lt;&nbsp;1&nbsp;&lt;&lt;&nbsp;2&nbsp;&lt;&lt;&nbsp;3</code></td>
  <td valign="top"></td>
  <td valign="top"><code>"\001\002\003"</code></td>
</tr>
<tr>
<td colspan="3" valign="top"><code></code></td>
</tr>
<tr>
  <td valign="top"><code>[&nbsp;4,&nbsp;5,&nbsp;6&nbsp;].pack("c*")</code></td>
  <td valign="top"></td>
  <td valign="top"><code>"\004\005\006"</code></td>
</tr>
</table>
<P></P>

<h3>But I Miss My C++ Iostream</h3>
<P></P>
Sometimes there's just no accounting for taste...However, just as you can append an object to an <code>Array</code> using the
<code>&lt;&lt;</code> operator, you can also append an object to an output <code>IO</code>
stream:
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
endl&nbsp;=&nbsp;"\n"
$stdout&nbsp;&lt;&lt;&nbsp;99&nbsp;&lt;&lt;&nbsp;"&nbsp;red&nbsp;balloons"&nbsp;&lt;&lt;&nbsp;endl
</pre></td></tr></table>

<em>produces:</em>
<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
99&nbsp;red&nbsp;balloons
</pre></td></tr></table>

<P></P>
Again, the <code>&lt;&lt;</code> method uses <code>to_s</code> to convert its
arguments to strings before sending them on their merry way.
<h2>Talking to Networks</h2>
<P></P>
Ruby is fluent in most of the Internet's protocols, both low-level and
high-level.
<P></P>
For those who enjoy groveling around at the network level, Ruby
comes with a set of classes in the socket library (documented starting 
on page 473). These classes give you access to TCP, UDP, SOCKS, and
Unix domain sockets, as well as any additional socket types supported
on your architecture. The library also provides helper classes to make
writing servers easier. Here's a simple program that gets information
about the ``oracle'' user on our local machine using the finger
protocol. 
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
require&nbsp;'socket'
client&nbsp;=&nbsp;TCPSocket.open('localhost',&nbsp;'finger')
client.send("oracle\n",&nbsp;0)&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;0&nbsp;means&nbsp;standard&nbsp;packet
puts&nbsp;client.readlines
client.close
</pre></td></tr></table>

<em>produces:</em>
<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
Login:&nbsp;oracle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;			Name:&nbsp;Oracle&nbsp;installation
Directory:&nbsp;/home/oracle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;	Shell:&nbsp;/bin/bash
Never&nbsp;logged&nbsp;in.
No&nbsp;Mail.
No&nbsp;Plan.
</pre></td></tr></table>

<P></P>
At a higher level, the lib/net set of library modules provides
handlers for a set of application-level protocols (currently FTP,
HTTP, POP, SMTP, and telnet). These are documented starting
on page 486. For example, the following program lists the
images that are displayed on the Pragmatic Programmer home page.
<P></P>

<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
require&nbsp;'net/http'
<P></P>
h&nbsp;=&nbsp;Net::HTTP.new('www.pragmaticprogrammer.com',&nbsp;80)
resp,&nbsp;data&nbsp;=&nbsp;h.get('/index.html',&nbsp;nil)
if&nbsp;resp.message&nbsp;==&nbsp;"OK"
&nbsp;&nbsp;data.scan(/&lt;img&nbsp;src="(.*?)"/)&nbsp;{&nbsp;|x|&nbsp;puts&nbsp;x&nbsp;}
end
</pre></td></tr></table>

<em>produces:</em>
<table bgcolor="#fff0f0" cellspacing="0" border="0" cellpadding="3" width="400"><tr><td><pre>
images/title_main.gif
images/dot.gif
images/dot.gif
images/dot.gif
images/dot.gif
images/dot.gif
</pre></td></tr></table>

<P></P>

<p></p><hr><table bgcolor="#a03030" cellpadding="10" border="0" cellspacing="0"><tr><td width="33%" align="left"><a class="subheader" href="tut_modules.html">Previous &lt;</a></td><td width="33%" align="center" valign="middle"><a class="subheader" href="index.html">Contents ^</a><br></td><td width="33%" align="right"><a class="subheader" href="tut_threads.html">Next ></a><br></td></tr></table><p></p><font size="-1">Extracted from the book "Programming Ruby -
     The Pragmatic Programmer's Guide"</font><br><font size="-3">
      Copyright
      &#169;
      2000 Addison Wesley Longman, Inc. Released under the terms of the
      <a href="http://www.opencontent.org/openpub/">Open Publication License</a> V1.0.
        <br>
      This reference is available for
        <a href="http://www.pragmaticprogrammer.com/ruby/downloads/book.html">download</a>.
   </font></body></html>