rio 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +225 -0
- data/README +12 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/doc/ANNOUNCE +160 -71
- data/doc/RELEASE_NOTES +71 -2
- data/ex/colx.rb +1 -1
- data/ex/passwd_report.rb +4 -8
- data/ex/riocat +5 -5
- data/ex/riogunzip +1 -1
- data/ex/riogzip +6 -6
- data/ex/rioprompt.rb +6 -0
- data/lib/rio.rb +3 -13
- data/lib/rio/arycopy.rb +1 -1
- data/lib/rio/base.rb +1 -5
- data/lib/rio/construct.rb +75 -0
- data/lib/rio/constructor.rb +42 -11
- data/lib/rio/context.rb +1 -1
- data/lib/rio/context/dir.rb +50 -23
- data/lib/rio/context/methods.rb +5 -3
- data/lib/rio/{cxdir.rb → context/skip.rb} +24 -36
- data/lib/rio/context/stream.rb +38 -16
- data/lib/rio/cp.rb +24 -5
- data/lib/rio/dir.rb +8 -7
- data/lib/rio/doc/HOWTO.rb +33 -33
- data/lib/rio/doc/INTRO.rb +416 -256
- data/lib/rio/doc/MISC.rb +3 -1
- data/lib/rio/doc/SYNOPSIS.rb +28 -33
- data/lib/rio/entrysel.rb +76 -9
- data/lib/rio/file.rb +2 -1
- data/lib/rio/filter.rb +95 -0
- data/lib/rio/filter/closeoneof.rb +1 -1
- data/lib/rio/grande.rb +0 -74
- data/lib/rio/if.rb +2 -1
- data/lib/rio/if/basic.rb +1 -1
- data/lib/rio/if/csv.rb +1 -1
- data/lib/rio/if/dir.rb +1 -220
- data/lib/rio/if/fileordir.rb +26 -12
- data/lib/rio/if/grande.rb +55 -6
- data/lib/rio/if/grande_entry.rb +355 -0
- data/lib/rio/if/{methods.rb → grande_stream.rb} +69 -88
- data/lib/rio/if/path.rb +25 -3
- data/lib/rio/if/stream.rb +62 -37
- data/lib/rio/if/temp.rb +2 -2
- data/lib/rio/if/test.rb +23 -0
- data/lib/rio/impl/path.rb +5 -0
- data/lib/rio/match.rb +6 -3
- data/lib/rio/matchrecord.rb +50 -46
- data/lib/rio/{filter/chomp.rb → ops/construct.rb} +12 -20
- data/lib/rio/ops/create.rb +3 -0
- data/lib/rio/ops/dir.rb +12 -6
- data/lib/rio/ops/either.rb +17 -3
- data/lib/rio/ops/path.rb +4 -1
- data/lib/rio/ops/stream/input.rb +6 -1
- data/lib/rio/ops/stream/read.rb +1 -3
- data/lib/rio/{context/chomp.rb → prompt.rb} +17 -13
- data/lib/rio/rl/base.rb +1 -1
- data/lib/rio/rl/builder.rb +3 -1
- data/lib/rio/state.rb +7 -13
- data/lib/rio/stream.rb +8 -5
- data/lib/rio/stream/open.rb +1 -1
- data/lib/rio/version.rb +1 -1
- data/test/mswin32.rb +1 -1
- data/test/runtests_gem.rb +1 -1
- data/test/tc/all.rb +3 -0
- data/test/tc/copy-from.rb +13 -13
- data/test/tc/copy-to.rb +1 -1
- data/test/tc/copy.rb +1 -1
- data/test/tc/copydir.rb +0 -24
- data/test/tc/copysymlink.rb +39 -0
- data/test/tc/csv.rb +2 -2
- data/test/tc/csv2.rb +4 -4
- data/test/tc/misc.rb +16 -16
- data/test/tc/nolines.rb +26 -26
- data/test/tc/noqae.rb +74 -74
- data/test/tc/overload.rb +28 -28
- data/test/tc/riorl.rb +36 -0
- data/test/tc/selnosel.rb +36 -0
- data/test/tc/skip.rb +58 -0
- data/test/tc/skiplines.rb +42 -0
- data/test/tc/symlink.rb +1 -1
- data/test/tc/symlink0.rb +1 -1
- data/test/tc/temp.rb +1 -1
- data/test/tc/tempdir.rb +1 -1
- data/test/tc/testcase.rb +7 -1
- metadata +14 -8
- data/lib/rio/matchcolumns.rb +0 -266
- data/lib/rio/rangemath.rb +0 -44
data/lib/rio/doc/INTRO.rb
CHANGED
@@ -41,28 +41,31 @@ module Doc
|
|
41
41
|
|
42
42
|
= Rio - Ruby I/O Comfort Class
|
43
43
|
|
44
|
-
Rio is a convenience class wrapping much of the functionality of
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
allows many application level IO tasks to be accomplished in line or
|
44
|
+
Rio is a convenience class wrapping much of the functionality of IO,
|
45
|
+
File, Dir, Pathname, FileUtils, Tempfile, StringIO, and OpenURI and
|
46
|
+
uses Zlib, and CSV to extend that functionality using a simple
|
47
|
+
consistent interface. Most of the instance methods of IO, File and
|
48
|
+
Dir are simply forwarded to the appropriate handle to provide
|
49
|
+
identical functionality. Rio also provides a "grande" interface that
|
50
|
+
allows many application level IO tasks to be accomplished in line or
|
51
|
+
two of code.
|
51
52
|
|
52
53
|
Rio functionality can be broadly broken into three categories
|
53
54
|
* path manipulation
|
54
55
|
* file system access
|
55
56
|
* stream manipulation
|
56
57
|
|
57
|
-
Which methods are available to a given Rio, depends on the underlying
|
58
|
+
Which methods are available to a given Rio, depends on the underlying
|
59
|
+
object.
|
58
60
|
|
59
|
-
A Rio generally does not need to be opened or have its mode specified.
|
60
|
-
Most of Rio's methods simply configure it.
|
61
|
-
|
62
|
-
|
61
|
+
A Rio generally does not need to be opened or have its mode specified.
|
62
|
+
Most of Rio's methods simply configure it. When an actual IO
|
63
|
+
operation is specified, Rio determines how to open it based on the
|
64
|
+
object it is opening, the operation it is performing, and the options
|
65
|
+
specified.
|
63
66
|
|
64
|
-
Rio configuration methods return the Rio for easy chaining and regard
|
65
|
-
as an implied +each+.
|
67
|
+
Rio configuration methods return the Rio for easy chaining and regard
|
68
|
+
the presence of a block as an implied +each+.
|
66
69
|
|
67
70
|
== Using a Rio
|
68
71
|
|
@@ -73,15 +76,18 @@ Using a Rio can be described as having 3 steps:
|
|
73
76
|
|
74
77
|
=== Creating a Rio
|
75
78
|
|
76
|
-
Rio extends Kernel with one function +rio+, its constructor. This
|
77
|
-
create any type of Rio. +rio+ looks at the
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
Rio extends Kernel with one function +rio+, its constructor. This
|
80
|
+
function is overloaded to create any type of Rio. +rio+ looks at the
|
81
|
+
class and sometimes the value of its first argument to create an
|
82
|
+
internal representation of the resource specified, additional
|
83
|
+
arguments are used as needed by the resource type. The rio constructor
|
84
|
+
does not initiate any io, it does not check for a resources existance
|
85
|
+
or type. It neither knows nor cares what can be done with this Rio.
|
86
|
+
Using methods like <tt>respond_to?</tt> are meaningless at best and usually
|
87
|
+
misleading.
|
82
88
|
|
83
|
-
For purposes of discussion, we divide Rios into two catagories, those
|
84
|
-
and those that don't.
|
89
|
+
For purposes of discussion, we divide Rios into two catagories, those
|
90
|
+
that have a path and those that don't.
|
85
91
|
|
86
92
|
==== Creating a Rio that has a path
|
87
93
|
|
@@ -195,7 +201,8 @@ or
|
|
195
201
|
or
|
196
202
|
rio('tcp://hostname:port')
|
197
203
|
|
198
|
-
===== Creating a Rio that runs an external program and connects to its
|
204
|
+
===== Creating a Rio that runs an external program and connects to its
|
205
|
+
stdin and stdout
|
199
206
|
|
200
207
|
<tt>rio(?-,cmd)</tt> (mnemonic: '-' is used by some Unix programs to specify stdin or stdout in place of a file)
|
201
208
|
|
@@ -207,21 +214,22 @@ This is Rio's interface to IO#popen
|
|
207
214
|
|
208
215
|
=== Path Manipulation
|
209
216
|
|
210
|
-
Rio's path manipulation methods are for the most part simply forwarded
|
211
|
-
the return values converted to a Rio.
|
217
|
+
Rio's path manipulation methods are for the most part simply forwarded
|
218
|
+
to the File or URI classes with the return values converted to a Rio.
|
212
219
|
|
213
220
|
==== Creating a Rio from a Rio's component parts.
|
214
221
|
|
215
|
-
The Rio methods for creating a Rio from a Rio's component parts are
|
216
|
-
Rio#dirname, Rio#filename, Rio#basename, and Rio#extname.
|
217
|
-
|
218
|
-
configuration variable
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
+
The Rio methods for creating a Rio from a Rio's component parts are
|
223
|
+
Rio#dirname, Rio#filename, Rio#basename, and Rio#extname. The
|
224
|
+
behavior of Rio#basename depends on the setting of the +ext+
|
225
|
+
configuration variable and is different from its counterpart in the
|
226
|
+
File class. The default value of the +ext+ configuration variable is
|
227
|
+
the string returned File#extname. The +ext+ configuration variable can
|
228
|
+
be changed using Rio#ext and Rio#noext and can be queried using
|
229
|
+
Rio#ext?. This value is used by calls to Rio#basename.
|
222
230
|
|
223
|
-
Rio#filename returns the last component of a path, and is basically
|
224
|
-
of an extension.
|
231
|
+
Rio#filename returns the last component of a path, and is basically
|
232
|
+
the same as +basename+ without consideration of an extension.
|
225
233
|
|
226
234
|
rio('afile.txt').basename #=> rio('afile')
|
227
235
|
rio('afile.txt').filename #=> rio('afile.txt')
|
@@ -234,9 +242,10 @@ of an extension. So
|
|
234
242
|
|
235
243
|
==== Changing a path's component parts.
|
236
244
|
|
237
|
-
Rio also provides methods for changing the component parts of its
|
238
|
-
They are Rio#dirname=, Rio#filename=, Rio#basename=, and
|
239
|
-
methods replace the part extracted as described
|
245
|
+
Rio also provides methods for changing the component parts of its
|
246
|
+
path. They are Rio#dirname=, Rio#filename=, Rio#basename=, and
|
247
|
+
Rio#extname=. These methods replace the part extracted as described
|
248
|
+
above with their argument.
|
240
249
|
|
241
250
|
ario = rio('dirA/dirB/afile.rb')
|
242
251
|
ario.dirname = 'dirC' # rio('dirC/afile.rb')
|
@@ -244,31 +253,34 @@ methods replace the part extracted as described above with their argument.
|
|
244
253
|
ario.extname = '.txt' # rio('dirC/bfile.txt')
|
245
254
|
ario.filename = 'cfile.rb' # rio('dirC/cfile.rb')
|
246
255
|
|
247
|
-
Rio also has a +rename+ mode which causes each of these to rename the
|
248
|
-
object as well as changing the Rio. This is
|
249
|
-
Renaming and Moving.
|
250
|
-
|
256
|
+
Rio also has a +rename+ mode which causes each of these to rename the
|
257
|
+
actual file system object as well as changing the Rio. This is
|
258
|
+
discussed in the section on Renaming and Moving.
|
251
259
|
|
252
260
|
==== Splitting a Rio
|
253
261
|
|
254
|
-
Rio#split returns an array of Rios, one for each path element. (Note
|
255
|
-
from File#split.)
|
262
|
+
Rio#split returns an array of Rios, one for each path element. (Note
|
263
|
+
that this behavior differs from File#split.)
|
256
264
|
|
257
265
|
rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
|
258
266
|
|
259
|
-
The array returned is extended
|
267
|
+
The array returned is extended wwith a +to_rio+ method, which will put
|
268
|
+
the parts back together again.
|
260
269
|
|
261
270
|
ary = rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
|
262
271
|
ary.to_rio #=> rio('a/b/c')
|
263
272
|
|
264
273
|
==== Creating a Rio by specifying the individual parts of its path
|
265
274
|
|
266
|
-
The first way to create a Rio by specifying its parts is to use the
|
267
|
-
a Rio is among the arguments the
|
275
|
+
The first way to create a Rio by specifying its parts is to use the
|
276
|
+
Rio constructor Rio#rio. Since a Rio is among the arguments the
|
277
|
+
constructor will take, the constructor can be used.
|
278
|
+
|
268
279
|
ario = rio('adir')
|
269
280
|
rio(ario,'b') #=> rio('adir/b')
|
270
281
|
|
271
|
-
Rio#join and Rio#/ do the same thing, but the operator version
|
282
|
+
Rio#join and Rio#/ do the same thing, but the operator version
|
283
|
+
<tt>/</tt> can take only one argument.
|
272
284
|
|
273
285
|
a = rio('a')
|
274
286
|
b = rio('b')
|
@@ -284,9 +296,9 @@ The arguments to +join+ and <tt>/</tt> do not need to be Rios, of course
|
|
284
296
|
|
285
297
|
==== Manipulating a Rio path by treating it as a string.
|
286
298
|
|
287
|
-
The Rio methods which treat a Rio as a string are Rio#sub, Rio#gsub
|
288
|
-
These methods create a new Rio using the string created by
|
289
|
-
to the String returned by Rio#to_s.
|
299
|
+
The Rio methods which treat a Rio as a string are Rio#sub, Rio#gsub
|
300
|
+
and Rio#+. These methods create a new Rio using the string created by
|
301
|
+
forwarding the method to the String returned by Rio#to_s.
|
290
302
|
|
291
303
|
ario = rio('dirA/dirB/afile') + '-1.1.1' # rio('dirA/dirB/afile-1.1.1')
|
292
304
|
brio = ario.sub(/^dirA/, 'dirC') # rio('dirC/dirB/afile-1.1.1')
|
@@ -296,8 +308,8 @@ to the String returned by Rio#to_s.
|
|
296
308
|
|
297
309
|
Rio#abs creates a new rio whose path is the absolute path of a Rio.
|
298
310
|
If provided with an argument, it uses that as the base path, otherwise
|
299
|
-
it uses an internal base path (usually the current working directory
|
300
|
-
it was created).
|
311
|
+
it uses an internal base path (usually the current working directory
|
312
|
+
when it was created).
|
301
313
|
|
302
314
|
rio('/tmp').chdir do
|
303
315
|
rio('a').abs #=> rio('/tmp/a')
|
@@ -311,60 +323,85 @@ Rio#rel creates a new rio with a path relative to a Rio.
|
|
311
323
|
end
|
312
324
|
rio('/tmp/b').rel('/tmp') #=> rio('b')
|
313
325
|
|
314
|
-
Rio#route_to and Rio#route_from creates a new rio with a path
|
315
|
-
the route to get to/from a Rio. They are based on the
|
316
|
-
same names in the URI class
|
326
|
+
Rio#route_to and Rio#route_from creates a new rio with a path
|
327
|
+
representing the route to get to/from a Rio. They are based on the
|
328
|
+
methods of the same names in the URI class
|
317
329
|
|
318
330
|
=== Configuring a Rio
|
319
331
|
|
320
|
-
The second step in using a rio is configuring it. Note that many times
|
321
|
-
and that this is not a comprehensive
|
332
|
+
The second step in using a rio is configuring it. Note that many times
|
333
|
+
no configuration is necessary and that this is not a comprehensive
|
334
|
+
list of all of Rio's configuration methods.
|
322
335
|
|
323
336
|
Rio's configuration mehods fall into three categories.
|
324
337
|
|
325
338
|
[IO manipulators]
|
326
|
-
|
327
|
-
|
339
|
+
|
340
|
+
An IO manipulator alters the behavior of a Rio's underlying IO
|
341
|
+
object. These affect the behaviour of I/O methods which are
|
342
|
+
forwarded directly to the underlying object as well as the grande
|
343
|
+
I/O methods.
|
328
344
|
|
329
345
|
[Grande configuration methods]
|
330
|
-
|
346
|
+
|
347
|
+
The grande configuration methods affect the behaviour of Rio's
|
348
|
+
grande I/O methods
|
331
349
|
|
332
350
|
[Grande selection methods]
|
333
|
-
The grande selection methods select what data is returned by Rio's grande I/O methods
|
334
351
|
|
335
|
-
|
336
|
-
|
352
|
+
The grande selection methods select what data is returned by Rio's
|
353
|
+
grande I/O methods
|
354
|
+
|
355
|
+
All of Rio's configuration and selection methods can be passed a
|
356
|
+
block, which will cause the Rio to behave as if +each+ had been called
|
357
|
+
with the block after the method.
|
337
358
|
|
338
359
|
==== IO manipulators
|
339
360
|
|
340
361
|
* +gzip+ a file on output, and ungzip it on input
|
362
|
+
|
341
363
|
rio('afile.gz').gzip
|
342
|
-
|
364
|
+
|
365
|
+
This causes the rio to read through a Zlib::GzipReader and to write
|
366
|
+
Zlib::GzipWriter.
|
343
367
|
|
344
368
|
* +chomp+ lines as they are read
|
369
|
+
|
345
370
|
rio('afile').chomp
|
346
|
-
|
371
|
+
|
372
|
+
This causes a Rio to call String#chomp on the the String returned by
|
373
|
+
all line oriented read operations.
|
347
374
|
|
348
375
|
==== Grande configuration methods
|
349
376
|
|
350
377
|
* +all+, +recurse+, +norecurse+
|
378
|
+
|
351
379
|
rio('adir').all
|
352
380
|
rio('adir').norecurse('CVS')
|
353
|
-
|
354
|
-
|
381
|
+
|
382
|
+
These methods instruct the Rio to also include entries in
|
383
|
+
subdirectories when iterating through directories and control which
|
384
|
+
subdirectories are included or excluded.
|
355
385
|
|
356
386
|
* +bytes+
|
387
|
+
|
357
388
|
rio('afile').bytes(1024)
|
358
|
-
|
389
|
+
|
390
|
+
This causes a Rio to read the specified number of bytes at a time as
|
391
|
+
a file is iterated through.
|
359
392
|
|
360
393
|
==== Grande selection methods
|
361
394
|
|
362
|
-
* +lines+, +
|
395
|
+
* +lines+, +skiplines+
|
396
|
+
|
363
397
|
rio('afile').lines(0..9)
|
364
|
-
rio('afile').
|
365
|
-
|
366
|
-
|
367
|
-
|
398
|
+
rio('afile').skiplines(/^\s*#/)
|
399
|
+
|
400
|
+
Strictly speaking these are both configuration and selection
|
401
|
+
methods. They configure the Rio to iterate through an input stream
|
402
|
+
as lines. The arguments select which lines are actually returned.
|
403
|
+
Lines are included (+lines+) or excluded (+skiplines+) if they match
|
404
|
+
*any* of the arguments as follows.
|
368
405
|
|
369
406
|
If the argument is a:
|
370
407
|
+RegExp+:: the line is matched against it
|
@@ -372,28 +409,35 @@ All of Rio's configuration and selection methods can be passed a block, which wi
|
|
372
409
|
+Integer+:: the lineno is matched against it as if it were a one element range
|
373
410
|
+Symbol+:: the symbol is +sent+ to the string; the line is included unless it returns false
|
374
411
|
+Proc+:: the proc is called with the line as an argument; the line is included unless it returns false
|
412
|
+
+Array+:: an array containing any of the above, all of which must match for the line to be included
|
375
413
|
|
376
|
-
* +entries+, +files+, +dirs+, +
|
414
|
+
* +entries+, +files+, +dirs+, +skipentries+, +skipfiles+, +skipdirs+
|
377
415
|
|
378
416
|
rio('adir').files('*.txt')
|
379
|
-
rio('adir').
|
417
|
+
rio('adir').skipfiles(/^\./)
|
380
418
|
|
381
|
-
These methods select which entries will be returned when iterating
|
382
|
-
Entries are included (+entries+,+files+,+dirs+)
|
383
|
-
match *any* of
|
419
|
+
These methods select which entries will be returned when iterating
|
420
|
+
throug directories. Entries are included (+entries+,+files+,+dirs+)
|
421
|
+
or excluded(+skipentries+,+skipfiles+,+skipdirs+) if they match *any* of
|
422
|
+
the arguments as follows.
|
384
423
|
|
385
424
|
If the argument is a:
|
386
425
|
+String+:: the arg is treated as a glob; the filname is matched against it
|
387
426
|
+RegExp+:: the filname is matched against it
|
388
427
|
+Symbol+:: the symbol is +sent+ to the entry (a Rio); the entry is included unless it returns false
|
389
428
|
+Proc+:: the proc is called with the entry (a Rio) as an argument; the entry is included unless it returns false
|
429
|
+
+Array+:: an array containing any of the above, all of which must match for the line to be included
|
430
|
+
|
431
|
+
* +records+, +rows+, +skiprecords+, +skiprows+
|
390
432
|
|
391
|
-
* +records+, +rows+, +norecords+, +norows+
|
392
433
|
rio('afile').bytes(1024).records(0...10)
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
434
|
+
|
435
|
+
These select items from an input stream just as +lines+, but without
|
436
|
+
specifying lines as the input record type. They can be used to
|
437
|
+
select different record types in extension modules. The only such
|
438
|
+
module at this writing is the CSV extension. In that case +records+
|
439
|
+
causes each line of a CSV file to be parsed into an array while
|
440
|
+
+lines+ causes each line of the file to be returned normally.
|
397
441
|
|
398
442
|
=== Rio I/O
|
399
443
|
|
@@ -404,11 +448,14 @@ As stated above the the three steps to using a Rio are:
|
|
404
448
|
|
405
449
|
This section describes that final step.
|
406
450
|
|
407
|
-
After creating and configuring a Rio, the file-system has not been
|
408
|
-
not so much as a test for a files
|
409
|
-
|
410
|
-
|
411
|
-
|
451
|
+
After creating and configuring a Rio, the file-system has not been
|
452
|
+
accessed, no socket has been opened, not so much as a test for a files
|
453
|
+
existance has been done. When an I/O method is called on a Rio, the
|
454
|
+
sequence of events required to complete that operation on the
|
455
|
+
underlying object takes place. Rio takes care of creating the
|
456
|
+
apropriate object (eg IO,Dir), opening the object with the apropriate
|
457
|
+
mode, performing the operation, closing the object if required, and
|
458
|
+
returning the results of the operation.
|
412
459
|
|
413
460
|
Rio's I/O operations can be divide into two catagories:
|
414
461
|
* Proxy operations
|
@@ -416,107 +463,175 @@ Rio's I/O operations can be divide into two catagories:
|
|
416
463
|
|
417
464
|
==== Proxy operations
|
418
465
|
|
419
|
-
These are calls which are forwarded to the underlying object (eg
|
420
|
-
creating and configuring that
|
421
|
-
the
|
466
|
+
These are calls which are forwarded to the underlying object (eg
|
467
|
+
IO,Dir,Net::FTP), after apropriately creating and configuring that
|
468
|
+
object. The result produced by the method is returned, and the object
|
469
|
+
is closed.
|
422
470
|
|
423
|
-
In some cases the result is modified before being returned, as when a
|
471
|
+
In some cases the result is modified before being returned, as when a
|
472
|
+
Rio is configured with +chomp+.
|
424
473
|
|
425
|
-
In all cases, if the result returned by the underlying object, could
|
426
|
-
operations it is returned as a Rio. For
|
427
|
-
|
428
|
-
returns a
|
474
|
+
In all cases, if the result returned by the underlying object, could
|
475
|
+
itself be used for further I/O operations it is returned as a Rio. For
|
476
|
+
example: where File#dirname returns a string, Rio#dirname returns a
|
477
|
+
Rio; where Dir#read returns a string representing a directory entry,
|
478
|
+
Rio#read returns a Rio.
|
429
479
|
|
430
|
-
With some noteable exceptions, most of the operations available if one
|
431
|
-
Ruby I/O class are available to the Rio and
|
480
|
+
With some noteable exceptions, most of the operations available if one
|
481
|
+
were using the underlying Ruby I/O class are available to the Rio and
|
482
|
+
will behave identically.
|
432
483
|
|
433
484
|
For things that exist on a file system:
|
434
|
-
|
485
|
+
|
486
|
+
* All the methods in FileTest are available as Rio instance
|
487
|
+
methods. For example
|
488
|
+
|
435
489
|
FileTest.file?('afile')
|
490
|
+
|
436
491
|
becomes
|
492
|
+
|
437
493
|
rio('afile').file?
|
438
|
-
|
494
|
+
|
495
|
+
* All the instance methods of +File+ except +path+ are available to a
|
496
|
+
rio without change
|
497
|
+
|
439
498
|
* Most of the class methods of +File+ are available.
|
440
|
-
|
441
|
-
|
499
|
+
|
500
|
+
* For those that take a filename as their only argument the calls
|
501
|
+
are mapped to Rio instance methods as described above for
|
502
|
+
FileTest.
|
503
|
+
|
442
504
|
* +dirname+, and +readlink+ return Rios instead of strings
|
443
|
-
|
444
|
-
*
|
445
|
-
|
505
|
+
|
506
|
+
* Rio has its own Rio#basename, Rio#join and Rio#symlink, which
|
507
|
+
provide similar functionality.
|
508
|
+
|
509
|
+
* The class methods which take multiple filenames
|
510
|
+
(+chmod+,+chown+,+lchmod+,+lchown+) are available as Rio instance
|
511
|
+
methods. For example
|
512
|
+
|
446
513
|
File.chmod(0666,'afile')
|
447
514
|
becomes
|
448
515
|
rio('afile').chmod(06660)
|
449
516
|
|
450
517
|
For I/O Streams
|
451
518
|
|
452
|
-
Most of the instance methods of IO are available, and most do the same
|
453
|
-
<b>The big exception to this is
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
519
|
+
Most of the instance methods of IO are available, and most do the same
|
520
|
+
thing, with some interface changes. <b>The big exception to this is
|
521
|
+
the '<<' operator.</b> This is one of Rio's grande operators. While
|
522
|
+
the symantics one would use to write to an IO object would actually
|
523
|
+
accomplish the same thing with a Rio, It is a very different
|
524
|
+
operator. Read the section on grande operators. The other differences
|
525
|
+
between IO instance methods and the Rio equivelence can be summarized
|
526
|
+
as follows.
|
527
|
+
|
528
|
+
* The simple instance methods (eg +fcntl+, <tt>eof?</tt>,
|
529
|
+
<tt>tty?</tt> etc.) are forwarded and the result returned as is
|
530
|
+
|
459
531
|
* Anywhere IO returns an IO, Rio returns a Rio
|
532
|
+
|
460
533
|
* +close+ and its cousins return the Rio.
|
534
|
+
|
461
535
|
* +each_byte+ and +each_line+ are forwarded as is.
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
536
|
+
|
537
|
+
* All methods which read (read*,get*,each*) will cause the file to
|
538
|
+
closed when the end of file is reached. This behavior is
|
539
|
+
configurable, but the default is to close on eof
|
540
|
+
|
541
|
+
* The methods which write (put*,print*) are forwarded as is; put* and
|
542
|
+
print* return the Rio; write returns the value returned by IO#write;
|
543
|
+
as mentioned above '<<' is a grande operator in Rio.
|
466
544
|
|
467
545
|
For directories:
|
468
546
|
|
469
|
-
* all the instance methods of Dir are available except +each+ which is
|
470
|
-
|
471
|
-
|
472
|
-
*
|
547
|
+
* all the instance methods of Dir are available except +each+ which is
|
548
|
+
a grande method.
|
549
|
+
|
550
|
+
* the class methods +mkdir+, +delete+, +rmdir+ are provided as
|
551
|
+
instance methods.
|
552
|
+
|
553
|
+
* +chdir+ is provided as an instance method. Rio#chdir returns a Rio
|
554
|
+
and passes a Rio to a block if one is provided.
|
555
|
+
|
556
|
+
* +glob+ is provided as an instance method, but returns an array of
|
557
|
+
Rios
|
558
|
+
|
473
559
|
* +foreach+ is not supported
|
560
|
+
|
474
561
|
* +each+ and <tt>[]</tt> have similar functionality provided by Rio
|
475
562
|
|
476
563
|
|
477
|
-
For other Rios, instance methods are generally forwarded where
|
564
|
+
For other Rios, instance methods are generally forwarded where
|
565
|
+
appropriate. For example
|
478
566
|
|
479
567
|
* Rios that refer to StringIO objects forward 'string' and 'string='
|
480
|
-
|
568
|
+
|
569
|
+
* Rios that refer to http URIs support all the Meta methods provided
|
570
|
+
by open-uri
|
481
571
|
|
482
572
|
|
483
573
|
==== Grande operators
|
484
574
|
|
485
|
-
The primary grande operator is Rio#each. +each+ is used to iterate
|
486
|
-
|
487
|
-
the
|
488
|
-
the
|
489
|
-
|
490
|
-
|
575
|
+
The primary grande operator is Rio#each. +each+ is used to iterate
|
576
|
+
through Rios. When applied to a file it iterates through records in
|
577
|
+
the file. When applied to a directory it iterates through the entries
|
578
|
+
in the directory. Its behavior is modified by configuring the Rio
|
579
|
+
prior to calling it using the configuration methods discussed
|
580
|
+
above. Since iterating through things is ubiquitous in ruby, it is
|
581
|
+
implied by the presence of a block after any of the grande
|
582
|
+
configuration methods and many times does not need to be call
|
583
|
+
explicitly. For example:
|
584
|
+
|
585
|
+
# iterate through chomped ruby comment lines
|
586
|
+
rio('afile.rb').chomp.lines(/^\s*#/) { |line| ... }
|
587
|
+
|
588
|
+
# iterate through all .rb files in 'adir' and its subdirectories
|
589
|
+
rio('adir').all.files('*.rb') { |f| ... }
|
491
590
|
|
492
|
-
|
493
|
-
|
591
|
+
Because a Rio is an Enumerable, it supports +to_a+, which is the basis
|
592
|
+
for the grande subscript operator. Rio#[] with no arguments simply
|
593
|
+
calls to_a. With arguments it behaves as if those arguments had been
|
594
|
+
passed to the most recently called of the grande selection methods
|
595
|
+
listed above, and then calls to_a. For example to get the first ten
|
596
|
+
lines of a file into an array with lines chomped
|
494
597
|
|
495
|
-
Because a Rio is an Enumerable, it supports +to_a+, which is the basis for the grande subscript operator.
|
496
|
-
Rio#[] with no arguments simply calls to_a. With arguments it behaves as if those arguments had been
|
497
|
-
passed to the most recently called of the grande selection methods listed above, and then calls to_a. For example
|
498
|
-
to get the first ten lines of a file into an array with lines chomped
|
499
598
|
rio('afile').chomp.lines(0...10).to_a
|
599
|
+
|
500
600
|
can be written as
|
601
|
+
|
501
602
|
rio('afile.gz').chomp.lines[0...10]
|
502
|
-
|
603
|
+
|
604
|
+
or, to create an array of all the .c files in a directory, one could
|
605
|
+
write
|
606
|
+
|
503
607
|
rio('adir').files['*.c']
|
504
608
|
|
505
609
|
The other grande operators are its copy operators. They are:
|
610
|
+
|
506
611
|
* <tt><</tt> (copy-from)
|
612
|
+
|
507
613
|
* <tt><<</tt> (append-from)
|
614
|
+
|
508
615
|
* <tt>></tt> (copy-to)
|
616
|
+
|
509
617
|
* <tt>>></tt> (append-to)
|
510
|
-
|
511
|
-
|
512
|
-
|
618
|
+
|
619
|
+
The only difference between the 'copy' and 'append' versions is how
|
620
|
+
they deal with an unopened resource. In the former the open it with
|
621
|
+
mode 'w' and in the latter, mode 'a'. Beyond that, their behavior can
|
622
|
+
be summarized as:
|
623
|
+
|
513
624
|
source.each do |entry|
|
514
625
|
destination << entry
|
515
626
|
end
|
516
|
-
|
517
|
-
|
627
|
+
|
628
|
+
Since they are based on the +each+ operator, all of the selection and
|
629
|
+
configuration options are available. And the right-hand-side argument
|
630
|
+
of the operators are not restricted to Rios -- Strings and Arrays are
|
631
|
+
also supported.
|
518
632
|
|
519
633
|
For example:
|
634
|
+
|
520
635
|
rio('afile') > astring # copy a file into a string
|
521
636
|
|
522
637
|
rio('afile').chomp > anarray # copy the chomped lines of afile into an array
|
@@ -529,31 +644,34 @@ For example:
|
|
529
644
|
|
530
645
|
rio('adir').dirs.files('README') > rio('bdir') # same thing, but only README files
|
531
646
|
|
532
|
-
rio(?-,'ps -a').
|
647
|
+
rio(?-,'ps -a').skiplines(0,/ps$/) > anarray # copy the output of th ps command into an array, skippying
|
533
648
|
# the header line and the ps command entry
|
534
649
|
|
535
650
|
=== Renaming and Moving
|
536
651
|
|
537
|
-
Rio provides two methods for directly renaming objects on the
|
538
|
-
Rio#rename and Rio#rename!. Both of these use
|
539
|
-
between them is the returned
|
540
|
-
|
652
|
+
Rio provides two methods for directly renaming objects on the
|
653
|
+
filesystem: Rio#rename and Rio#rename!. Both of these use
|
654
|
+
File#rename. The difference between them is the returned
|
655
|
+
Rio. Rio#rename leaves the path of the Rio unchanged, while
|
656
|
+
Rio#rename! changes the path of the Rio to refer to the renamed path.
|
657
|
+
|
541
658
|
ario = rio('a')
|
542
659
|
ario.rename('b') # file 'a' has been renamed to 'b' but 'ario' => rio('a')
|
543
660
|
ario.rename!('b') # file 'a' has been renamed to 'b' and 'ario' => rio('b')
|
544
661
|
|
545
|
-
Rio also has a +rename+ mode, which causes the path manipulation
|
546
|
-
Rio#filename=, Rio#basename= and Rio#extname= to
|
547
|
-
when they are used to change a
|
548
|
-
calling Rio#rename with
|
662
|
+
Rio also has a +rename+ mode, which causes the path manipulation
|
663
|
+
methods Rio#dirname=, Rio#filename=, Rio#basename= and Rio#extname= to
|
664
|
+
rename an object on the filesystem when they are used to change a
|
665
|
+
Rio's path. A Rio is put in +rename+ mode by calling Rio#rename with
|
666
|
+
no arguments.
|
549
667
|
|
550
668
|
rio('adir/afile.txt').rename.filename = 'bfile.rb' # adir/afile.txt => adir/bfile.rb
|
551
669
|
rio('adir/afile.txt').rename.basename = 'bfile' # adir/afile.txt => adir/bfile.txt
|
552
670
|
rio('adir/afile.txt').rename.extname = '.rb' # adir/afile.txt => adir/afile.rb
|
553
671
|
rio('adir/afile.txt').rename.dirname = 'b/c' # adir/afile.txt => b/c/afile.txt
|
554
672
|
|
555
|
-
When +rename+ mode is set for a directory Rio, it is automatically set
|
556
|
-
when iterating through that directory.
|
673
|
+
When +rename+ mode is set for a directory Rio, it is automatically set
|
674
|
+
in the Rios created when iterating through that directory.
|
557
675
|
|
558
676
|
rio('adir').rename.files('*.htm') do |frio|
|
559
677
|
frio.extname = '.html' #=> changes the rio and renames the file
|
@@ -561,10 +679,11 @@ when iterating through that directory.
|
|
561
679
|
|
562
680
|
=== Deleting
|
563
681
|
|
564
|
-
The Rio methods for deleting filesystem objects are Rio#rm, Rio#rmdir,
|
565
|
-
and Rio#delete!. +rm+, +rmdir+ and +rmtree+
|
566
|
-
|
567
|
-
calls
|
682
|
+
The Rio methods for deleting filesystem objects are Rio#rm, Rio#rmdir,
|
683
|
+
Rio#rmtree, Rio#delete, and Rio#delete!. +rm+, +rmdir+ and +rmtree+
|
684
|
+
are passed the like named methods in the FileUtils module. Rio#delete
|
685
|
+
calls +rmdir+ for directories and +rm+ for anything else, while
|
686
|
+
Rio#delete! calls Rio#rmtree for directories.
|
568
687
|
|
569
688
|
* To delete something only if it is not a directory use Rio#rm
|
570
689
|
* To delete an empty directory use Rio#rmdir
|
@@ -572,13 +691,17 @@ calls Rio#rmtree for directories.
|
|
572
691
|
* To delete anything except a populated directory use Rio#delete
|
573
692
|
* To delete anything use Rio#delete!
|
574
693
|
|
575
|
-
It is not an error to call any of the deleting methods on something
|
576
|
-
Rio#exist? and Rio#symlink? to check
|
577
|
-
|
578
|
-
|
579
|
-
|
694
|
+
It is not an error to call any of the deleting methods on something
|
695
|
+
that does not exist. Rio provides Rio#exist? and Rio#symlink? to check
|
696
|
+
if something exists (<tt>exist?</tt> returns false for symlinks to
|
697
|
+
non-existant object even though the symlink itself exists). The
|
698
|
+
deleting methods' purpose is to make things not exist, so calling one
|
699
|
+
of them on something that already does not exist is considered a
|
700
|
+
success.
|
701
|
+
|
702
|
+
To create a clean copy of a directory whether or not anything with
|
703
|
+
that name exists one might do this
|
580
704
|
|
581
|
-
To create a clean copy of a directory whether or not anything with that name exists one might do this
|
582
705
|
rio('adir').delete!.mkpath.chdir do
|
583
706
|
# do something in adir
|
584
707
|
end
|
@@ -590,37 +713,47 @@ To create a clean copy of a directory whether or not anything with that name exi
|
|
590
713
|
|
591
714
|
==== Using Symbolic Links
|
592
715
|
|
593
|
-
To create a symbolic link (symlink) to the file-system entry refered
|
594
|
-
Rio#symlink differs from File#symlink
|
595
|
-
the Rio's
|
716
|
+
To create a symbolic link (symlink) to the file-system entry refered
|
717
|
+
to by a Rio, use Rio#symlink. Rio#symlink differs from File#symlink
|
718
|
+
in that it calculates the path from the symlink location to the Rio's
|
719
|
+
position.
|
596
720
|
|
597
721
|
File#symlink('adir/afile','adir/alink')
|
598
722
|
|
599
|
-
creates a symlink in the directory 'adir' named 'alink' which
|
600
|
-
perspective of 'alink', 'adir/afile'
|
723
|
+
creates a symlink in the directory 'adir' named 'alink' which
|
724
|
+
references 'adir/afile'. From the perspective of 'alink', 'adir/afile'
|
725
|
+
does not exist. While:
|
601
726
|
|
602
727
|
rio('adir/afile').symlink('adir/alink')
|
603
728
|
|
604
|
-
creates a symlink in the directory 'adir' named 'alink' which
|
605
|
-
|
729
|
+
creates a symlink in the directory 'adir' named 'alink' which
|
730
|
+
references 'afile'. This is the route to 'adir/afile' from the
|
731
|
+
perspective of 'adir/alink'.
|
606
732
|
|
607
|
-
Note that the return value from +symlink+ is the calling Rio and not a
|
608
|
-
This is done for consistency with the
|
733
|
+
Note that the return value from +symlink+ is the calling Rio and not a
|
734
|
+
Rio refering to the symlink. This is done for consistency with the
|
735
|
+
rest of Rio.
|
736
|
+
|
737
|
+
Rio#symlink? can be used to test if a file-system object is a
|
738
|
+
symlink. A Rio is extended with Rio#readlink, and Rio#lstat only if
|
739
|
+
Rio#symlink? returns true. So for non-symlinks, these will raise a
|
740
|
+
NoMethodError. These are both passed to their counterparts in
|
741
|
+
File. Rio#readlink returns a Rio refering to the result of
|
742
|
+
File#readlink.
|
609
743
|
|
610
|
-
Rio#symlink? can be used to test if a file-system object is a symlink. A Rio is extended with
|
611
|
-
Rio#readlink, and Rio#lstat only if Rio#symlink? returns true. So for non-symlinks, these
|
612
|
-
will raise a NoMethodError. These are both passed to their counterparts in File. Rio#readlink
|
613
|
-
returns a Rio refering to the result of File#readlink.
|
614
744
|
|
615
745
|
==== Using A Rio as an IO (or File or Dir)
|
616
746
|
|
617
|
-
Rio supports so much of IO's interface that one might be tempted to
|
618
|
-
expects an IO. While Rio is not and is not
|
619
|
-
|
747
|
+
Rio supports so much of IO's interface that one might be tempted to
|
748
|
+
pass it to a method that expects an IO. While Rio is not and is not
|
749
|
+
intended to be a stand in for IO, this can work. It requires
|
750
|
+
knowledge of every IO method that will be called, under any
|
751
|
+
circumstances.
|
620
752
|
|
621
|
-
Even in cases where Rio supports the required IO interface, A Rio
|
622
|
-
cause the most incompatibility, is its automatic
|
623
|
-
automatic closing use
|
753
|
+
Even in cases where Rio supports the required IO interface, A Rio
|
754
|
+
feature that seems to cause the most incompatibility, is its automatic
|
755
|
+
closing of files. To turn off all of Rio's automatic closing use
|
756
|
+
Rio#noautoclose.
|
624
757
|
|
625
758
|
For example:
|
626
759
|
require 'yaml'
|
@@ -628,92 +761,110 @@ For example:
|
|
628
761
|
YAML.dump( ['badger', 'elephant', 'tiger'], yrio )
|
629
762
|
obj = YAML::load( yrio ) #=> ["badger", "tiger", "elephant"]
|
630
763
|
|
631
|
-
|
764
|
+
|
765
|
+
==== Automatically Closing Files
|
632
766
|
|
633
767
|
Rio closes files automatically in three instances.
|
634
768
|
|
635
|
-
When reading from an IO it is closed when the end of file is
|
636
|
-
this is a reasonable thing to do in many cases,
|
637
|
-
To turn Rio's automatic closing on end
|
638
|
-
be turned back on via
|
769
|
+
When reading from an IO it is closed when the end of file is
|
770
|
+
reached. While this is a reasonable thing to do in many cases,
|
771
|
+
sometimes this is not desired. To turn Rio's automatic closing on end
|
772
|
+
of file use Rio#nocloseoneof (it can be turned back on via
|
773
|
+
Rio#closeoneof)
|
639
774
|
|
640
775
|
ario = rio('afile').nocloseoneof
|
641
776
|
lines = ario[]
|
642
777
|
ario.closed? #=> false
|
643
778
|
|
644
|
-
Closing on end-of-file is necessary for many of Rio's
|
645
|
-
implication that may be surprising at first. A Rio starts life
|
646
|
-
much more than a string. When one of its read methods
|
647
|
-
input stream. When the stream is closed, it
|
648
|
-
that when reading from a Rio, the
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
779
|
+
Closing on end-of-file is necessary for many of Rio's one-liners, but
|
780
|
+
has an implication that may be surprising at first. A Rio starts life
|
781
|
+
as a path, not much more than a string. When one of its read methods
|
782
|
+
is called it becomes an input stream. When the stream is closed, it
|
783
|
+
becomes a path again. This means that when reading from a Rio, the
|
784
|
+
end-of-file condition is seen only once before it becomes a path
|
785
|
+
again, and will be reopened if another read operation is attempted.
|
786
|
+
|
787
|
+
Another time a Rio will be closed atomatically is when writing to it
|
788
|
+
with one of the copy operators (<tt><, <<, >, >></tt>). This behavior
|
789
|
+
can be turned off with Rio#nocloseoncopy.
|
790
|
+
|
791
|
+
To turn off both of thes types of automatic closing use
|
792
|
+
Rio#noautoclose.
|
793
|
+
|
794
|
+
The third instance when Rio will close a file automatically is when a
|
795
|
+
file opened for one type of access receives a method which that access
|
796
|
+
mode does not support. So, the code rio('afile').puts("Hello
|
797
|
+
World").gets will open the file for write access when the +puts+
|
798
|
+
method is received. When +gets+ is called the file is closed and
|
799
|
+
reopened with read access.
|
800
|
+
|
801
|
+
==== Explicitly Closing Files
|
802
|
+
|
803
|
+
Rio can not determine when the client is finished writing to it, as it
|
804
|
+
does using +eof+ on read. It is the author's understanding that Ruby
|
805
|
+
does not support a mechanism to have code run when there are no more
|
806
|
+
references to it -- that finalizers are not necessarily run immediatly
|
807
|
+
upon an object's reference count reaching 0. If this understanding is
|
808
|
+
incorrect, some of Rio's extranious ways of closing a file may be
|
809
|
+
rethought.
|
810
|
+
|
811
|
+
That being said, Rio support several ways to explicitly close a
|
812
|
+
file. Rio#close will close any open Rio. The output methods Rio#puts!,
|
813
|
+
Rio#putc!, Rio#printf!, Rio#print!, and Rio#write! behave as if their
|
814
|
+
counterparts without the exclamation point had been called and then
|
815
|
+
call Rio#close or Rio#close_write if the underlying IO object is
|
816
|
+
opened for duplex access.
|
677
817
|
|
678
818
|
|
679
819
|
==== Open mode selection
|
680
820
|
|
681
|
-
A Rio is typically not explicitly opened. It opens a file
|
682
|
-
input or output methed is called. For output
|
683
|
-
|
684
|
-
|
821
|
+
A Rio is typically not explicitly opened. It opens a file
|
822
|
+
automatically when an input or output methed is called. For output
|
823
|
+
methods Rio opens a file with mode 'w', and otherwise opens a file
|
824
|
+
with mode 'r'. This behavior can be modified using the tersely named
|
825
|
+
methods Rio#a, Rio#a!, Rio#r, Rio#r!, Rio#w, and Rio#w!, which cause
|
685
826
|
the Rio to use modes 'a','a+','r','r+','w',and 'w+' respectively.
|
686
827
|
|
687
828
|
One way to append a string to a file and close it in one line is
|
829
|
+
|
688
830
|
rio('afile').a.puts!("Hello World")
|
689
831
|
|
690
832
|
Run a cmd that must be opened for read and write
|
833
|
+
|
691
834
|
ans = rio(?-,'cat').w!.puts!("Hello Kitty").readlines
|
692
835
|
|
693
|
-
The automatic selection of mode can be bypassed entirely using
|
836
|
+
The automatic selection of mode can be bypassed entirely using
|
837
|
+
Rio#mode and Rio#open.
|
694
838
|
|
695
|
-
If a mode is specified using +mode+, the file will still be opened
|
696
|
-
the mode specified in the +mode+ method will be
|
839
|
+
If a mode is specified using +mode+, the file will still be opened
|
840
|
+
automatically, but the mode specified in the +mode+ method will be
|
841
|
+
used regardless of whether it makes sense.
|
697
842
|
|
698
|
-
A Rio can also be opened explicitly using Rio#open. +open+ takes one
|
699
|
-
This also will override all of Rio's automatic
|
843
|
+
A Rio can also be opened explicitly using Rio#open. +open+ takes one
|
844
|
+
parameter, a mode. This also will override all of Rio's automatic
|
845
|
+
mode selection.
|
700
846
|
|
701
847
|
|
702
848
|
==== CSV mode
|
703
849
|
|
704
|
-
Rio uses the CSV class from the Ruby standard library to provide
|
705
|
-
and writing comma-separated-value files. Normally
|
706
|
-
identical to <tt>(no)lines</tt> because
|
707
|
-
specify the record-type,
|
850
|
+
Rio uses the CSV class from the Ruby standard library to provide
|
851
|
+
support for reading and writing comma-separated-value files. Normally
|
852
|
+
using <tt>(no)records</tt> is identical to <tt>(no)lines</tt> because
|
853
|
+
while +records+ only selects and does not specify the record-type,
|
854
|
+
+lines+ is the default.
|
855
|
+
|
708
856
|
rio('afile').records(1..2)
|
857
|
+
|
709
858
|
effectively means
|
859
|
+
|
710
860
|
rio('afile').lines.records(1..2)
|
711
861
|
|
712
|
-
The CSV extension distingishes between items selected using
|
713
|
-
selected using Rio#lines. Rio returns records
|
714
|
-
|
715
|
-
+records+ is the
|
716
|
-
|
862
|
+
The CSV extension distingishes between items selected using
|
863
|
+
Rio#records and those selected using Rio#lines. Rio returns records
|
864
|
+
parsed into Arrays by the CSV library when +records+ is used, and
|
865
|
+
returns Strings as normal when +lines+ is used. +records+ is the
|
866
|
+
default.
|
867
|
+
|
717
868
|
rio('f.csv').puts!(["h0,h1","f0,f1"])
|
718
869
|
|
719
870
|
rio('f.csv').csv.records[] #==>[["h0", "h1"], ["f0", "f1"]]
|
@@ -722,23 +873,29 @@ So:
|
|
722
873
|
rio('f.csv').csv.records[0] #==>[["h0", "h1"]]
|
723
874
|
rio('f.csv').csv[0] #==> same thing
|
724
875
|
rio('f.csv').csv.lines[0] #==>["h0,h1\n"]
|
725
|
-
rio('f.csv').csv.
|
726
|
-
rio('f.csv').csv.
|
876
|
+
rio('f.csv').csv.skiprecords[0] #==>[["f0", "f1"]]
|
877
|
+
rio('f.csv').csv.skiplines[0] #==>["f0,f1\n"]
|
878
|
+
|
879
|
+
This distinction, of course, applies equally when using the copy
|
880
|
+
operators and +each+
|
727
881
|
|
728
|
-
This distinction, of course, applies equally when using the copy operators and +each+
|
729
882
|
rio('f.csv').csv[0] > rio('out').csv # out contains "f0,f1\n"
|
883
|
+
|
730
884
|
rio('f.csv').csv { |array_of_fields| ... }
|
731
885
|
|
732
|
-
Notice that +csv+ mode is called on both the input and output
|
733
|
-
'out' Rio causes it to treat an array written
|
734
|
-
|
735
|
-
|
886
|
+
Notice that +csv+ mode is called on both the input and output
|
887
|
+
Rios. The +csv+ on the 'out' Rio causes it to treat an array written
|
888
|
+
to it as an array of records which is converted into CSV format before
|
889
|
+
writing. Without the +csv+, the output would be written as if
|
890
|
+
Array#to_s on [["f0","f1"]] had been called
|
891
|
+
|
736
892
|
rio('f.csv').csv[0] > rio('out') # out contains "f0f1"
|
737
893
|
|
738
|
-
The String representing a record that is returned when using +lines+
|
739
|
-
+to_a+ method which will parse it into an array of
|
740
|
-
when a record is returned using
|
741
|
-
|
894
|
+
The String representing a record that is returned when using +lines+
|
895
|
+
is extended with a +to_a+ method which will parse it into an array of
|
896
|
+
fields. Likewise the Array returned when a record is returned using
|
897
|
+
+records+ is extended with a modified +to_s+ which treats it as an
|
898
|
+
array CSV fields, rather than just an array of strings.
|
742
899
|
|
743
900
|
array_of_lines = rio('f.csv').csv.lines[1] #==>["f0,f1\n"]
|
744
901
|
array_of_records = rio('f.csv').csv.records[1] #==>[["f0", "f1"]]
|
@@ -746,20 +903,22 @@ treats it as an array CSV fields, rather than just an array of strings.
|
|
746
903
|
array_of_lines[0].to_a #==>["f0", "f1"]
|
747
904
|
array_of_records[0].to_s #==>"f0,f1"
|
748
905
|
|
749
|
-
Rio#csv takes two optional parameters, which are passed on to the CSV
|
750
|
-
the +field_separator+ and the +record_separator+.
|
906
|
+
Rio#csv takes two optional parameters, which are passed on to the CSV
|
907
|
+
library. They are the +field_separator+ and the +record_separator+.
|
908
|
+
|
751
909
|
rio('semisep').puts!(["h0;h1","f0;f1"])
|
752
910
|
|
753
911
|
rio('semisep').csv(';').to_a #==>[["h0", "h1"], ["f0", "f1"]]
|
754
912
|
|
755
|
-
These are specified independently on the source and destination when
|
756
|
-
copy operators
|
913
|
+
These are specified independently on the source and destination when
|
914
|
+
using the copy operators.
|
757
915
|
|
758
916
|
rio('semisep').csv(';') > rio('colonsep').csv(':')
|
759
|
-
rio('colonsep').
|
917
|
+
rio('colonsep').contents #==>"h0:h1\nf0:f1\n"
|
760
918
|
|
761
|
-
Rio provides two methods for selecting fields from CSV records in a
|
762
|
-
to that provided for selecting lines -- Rio#columns and
|
919
|
+
Rio provides two methods for selecting fields from CSV records in a
|
920
|
+
manner similar to that provided for selecting lines -- Rio#columns and
|
921
|
+
Rio#nocolumns.
|
763
922
|
|
764
923
|
rio('f.csv').puts!(["h0,h1,h2,h3","f0,f1,f2,f3"])
|
765
924
|
|
@@ -768,10 +927,11 @@ to that provided for selecting lines -- Rio#columns and Rio#nocolumns.
|
|
768
927
|
rio('f.csv').csv.columns(1..2).to_a #==>[["h1", "h2"], ["f1", "f2"]]
|
769
928
|
rio('f.csv').csv.nocolumns(1..2).to_a #==>[["h0", "h3"], ["f0", "f3"]]
|
770
929
|
|
771
|
-
Rio#columns can, of course be used with the +each+ and the copy
|
930
|
+
Rio#columns can, of course be used with the +each+ and the copy
|
931
|
+
operators:
|
772
932
|
|
773
933
|
rio('f.csv').csv.columns(0..1) > rio('out').csv
|
774
|
-
rio('out').
|
934
|
+
rio('out').contents #==>"h0,h1\nf0,f1\n"
|
775
935
|
|
776
936
|
|
777
937
|
---
|