NAME IO::All - IO::All of it to Graham and Damian! NOTE If you've just read the perl.com article at , there have already been major additions thanks to the great feedback I've gotten from the Perl community. Be sure and read the latest doc. Things are changing fast. Many of the changes have to do with operator overloading for IO::All objects, which results in some fabulous new idioms. SYNOPSIS use IO::All; my $my_stuff = io('./mystuff')->slurp; # Read a file my $more_stuff < io('./morestuff'); # Read another file io('./allstuff')->print($my_stuff, $more_stuff); # Write to new file or like this: io('./mystuff') > io('./allstuff'); io('./morestuff') >> io('./allstuff'); or: my $stuff < io('./mystuff'); io('./morestuff') >> $stuff; io(./allstuff') << $stuff; or: ${io('./stuff')} . ${io('./morestuff')} > io('./allstuff'); SYNOPSIS II use IO::All; # Print name and first line of all files in a directory my $dir = io('./mydir'); while (my $io = $dir->next) { print $io->name, ' - ', $io->getline if $io->is_file; } # Print name of all files recursively print "$_\n" for io('./mydir')->All_Files; SYNOPSIS III use IO::All; # Various ways to copy STDIN to STDOUT io('-') > io('-'); io('-') < io('-'); io('-')->print(io('-')->slurp); my $stdin = io('-'); my $stdout = io('-'); $stdout->buffer($stdin->buffer); $stdout->write while $stdin->read; # Copy STDIN to a String File one line at a time my $stdin = io('-'); my $string_out = io('$'); while (my $line = $stdin->getline) { $string_out->print($line); } SYNOPSIS IV use IO::All; # A forking socket server that writes to a log my $server = io('server.com:9999'); my $socket = $server->accept('-fork'); while (my $msg = $socket->getline) { io('./mylog')->appendln(localtime() . ' - $msg'); } $socket->close; SYNOPSIS V use IO::All; # Write some data to a temporary file and retrieve all the paragraphs. my $temp = io; $temp->print($data); $temp->seek(0, 0); my @paragraphs = $temp->getlines(''); DESCRIPTION "Graham Barr for doing it all. Damian Conway for doing it all different." IO::All combines all of the best Perl IO modules into a single Spiffy object oriented interface to greatly simplify your everyday Perl IO idioms. It exports a single function called "io", which returns a new IO::All object. And that object can do it all! The IO::All object is a proxy for IO::File, IO::Dir, IO::Socket, IO::String, Tie::File and File::ReadBackwards. You can use most of the methods found in these classes and in IO::Handle (which they all inherit from). IO::All is easily subclassable. You can override any methods and also add new methods of your own. Optionally, every IO::All object can be tied to itself. This means that you can use most perl IO builtins on it: readline, <>, getc, print, printf, syswrite, sysread, close. (Due to an unfortunate bug in Perl 5.8.0 only, this option is turned off by default. See below.) The distinguishing magic of IO::All is that it will automatically open (and close) files, directories, sockets and io-strings for you. You never need to specify the mode ('<', '>>', etc), since it is determined by the usage context. That means you can replace this: open STUFF, '<', './mystuff' or die "Can't open './mystuff' for input:\n$!"; local $/; my $stuff = ; close STUFF; with this: my $stuff < io('./mystuff'); And that is a good thing! USAGE The use statement for IO::All can be passed several options: use IO::All (-tie => -lock => 1, ); All options begin with a '-' and come in two flavors: boolean options and key/value pair options. Boolean options can be followed by a 0 or a 1, or can stand alone; in which case they have an assumed value of 1. You can specify all options in any order without confusing IO::All. These options are simply defaults that are passed on to every "io" function within the program. Options * -tie Boolean. This option says that all objects created by the "io" function should be tied to themselves. use IO::All qw(-tie); my $io = io('file1'); my @lines = <$io>; $io->close; As you can see, you can use both method calls and builtin functions on the same object. NOTE: If you use the "-tie" option with Perl 5.8.0, you need may need to call the close function explicitly. Due to a bug, these objects will not go out of scope properly, thus the files opened for output will not be closed. This is not a problem in Perl 5.6.1 or 5.8.1 and greater. * -lock Boolean. This option tells the object to flock the filehandle after open. COOKBOOK This section describes some various things that you can easily cook up with IO::All. Operator Overloading IO::All objects stringify to their file or directory name. This command is a long way of doing "ls -1": perl -MIO::All -le 'print for io(".")->all' '>' and '<' move data between strings and files: $content < io('file1'); $content > io('file2'); io('file2') > $content2; io('file3') < $content2; io('file3') > io('file4'); io('file5') < io('file4'); '>>' and '<<' do the same thing except the recipent string or file is appended to. An IO::All file used as an array reference becomes tied using Tie::File: $file = io('file'); # Print last line of file print $file->[-1]; # Insert new line in middle of file $file->[$#{$file} / 2] = 'New line'; IO::All directories used as hashes have file names as keys, and IO::All objects as values: print io('dir')->{'foo.txt'}->slurp; Files used as scalar references get slurped: print ${io('dir')->{'foo.txt'}}; File Locking IO::All makes it very easy to lock files. Just use the "-lock" flag. Here's a standalone program that demonstrates locking for both write and read: use IO::All; my $io1 = io(-lock => 'myfile'); $io1->println('line 1'); fork or do { my $io2 = io(-lock => 'myfile'); print $io2->slurp; exit; }; sleep 1; $io1->println('line 2'); $io1->println('line 3'); $io1->unlock; There are a lot of subtle things going on here. An exclusive lock is issued for $io1 on the first "println". That's because the file isn't actually opened until the first IO operation. When the child process tries to read the file using $io2, there is a shared lock put on it. Since $io1 has the exclusive lock, the slurp blocks. The parent process sleeps just to make sure the child process gets a chance. The parent needs to call "unlock" or "close" to release the lock. If all goes well the child will print 3 lines. Round Robin This simple example will read lines from a file forever. When the last line is read, it will reopen the file and read the first one again. my $io = io('file1.txt'); $io->autoclose(1); while (my $line = $io->getline || $io->getline) { print $line; } Reading Backwards If you call the "backwards()" method on an IO::All object, the "getline()" and "getlines()" will work in reverse. They will read the lines in the file from the end to the beginning. my @reversed; my $io = io('file1.txt'); $io->backwards; while (my $line = $io->getline) { push @reversed, $line; } or more simply: my @reversed = io('file1.txt')->backwards->getlines; The "backwards()" method returns the IO::All object so that you can chain the calls. NOTE: This operation requires that you have the File::ReadBackwards module installed. Client/Server Sockets IO::All makes it really easy to write a forking socket server and a client to talk to it. In this example, a server will return 3 lines of text, to every client that calls it. Here is the server code: use IO::All; my $socket = io(':12345')->accept('-fork'); $socket->print($_) while ; $socket->close; __DATA__ On your mark, Get set, Go! Here is the client code: use IO::All; my $io = io('localhost:12345'); print while $_ = $io->getline; You can run the server once, and then run the client repeatedly (in another terminal window). It should print the 3 data lines each time. Note that it is important to close the socket if the server is forking, or else the socket won't go out of scope and close. File Subclassing Subclassing is easy with IO::All. Just create a new module and use IO::All as the base class. Since IO::All is a Spiffy module, you do it like this: package NewModule; use IO::All '-base'; You need to do it this way so that IO::All will export the "io" function. Here is a simple recipe for subclassing: IO::Dumper inherits everything from IO::All and adds an extra method called "dump()", which will dump a data structure to the file we specify in the "io" function. Since it needs Data::Dumper to do the dumping, we override the "open" method to "require Data::Dumper" and then pass control to the real "open". First the code using the module: use IO::Dumper; io('./mydump')->dump($hash); And next the IO::Dumper module itself: package IO::Dumper; use IO::All '-base'; use Data::Dumper; sub dump { my $self = shift; $self->print(Data::Dumper::Dumper(@_)); return $self; } 1; Inline Subclassing This recipe does the same thing as the previous one, but without needing to write a separate module. The only real difference is the first line. Since you don't "use" IO::Dumper, you need to still call its "import" method manually. IO::Dumper->import; io('./mydump')->dump($hash); package IO::Dumper; use IO::All '-base'; use Data::Dumper; sub dump { my $self = shift; $self->print(Data::Dumper::Dumper(@_)); return $self; } OPERATION NOTES * IO::All will automatically be opened when the first read or write happens. Mode is determined heuristically unless specified explicitly. * For input, IO::All objects will automatically be closed after EOF (or EOD). For output, the object closes when it goes out of scope. To keep input objects from closing at EOF, do this: $io->autoclose(0); * You can always call "open" and "close" explicitly, if you need that level of control. CONSTRUCTOR NOTE: The "io" function takes all the same parameters as "new". * new() new(file_descriptor, '-', '$', -file_name => $file_name, -file_handle => $file_handle, -dir_name => $directory_name, -dir_handle => $directory_handle, ); File descriptor is a file/directory name or file/directory handle or anything else that can be used in IO operations. IO::All will use STDIN or STDOUT (depending on context) if file descriptor is '-'. It will use an IO::String object if file descriptor is '$'. If file_descriptor is missing and neither "-file_handle" nor "-dir_handle" is specified, IO::All will create a temporary file which will be opened for both input and output. "-tie" uses the tie interface for a single object. INSTANCE METHODS IO::All provides lots of methods for making your daily programming tasks simpler. If you can't find what you need, just subclass IO::All and add your own. * accept() For sockets. Opens a server socket (LISTEN => 1, REUSE => 1). Returns an IO::All socket object that you are listening on. If the '-fork' option is specified, the process will automatically be forked for every connection. * all() Return a list of IO::All objects for all files and subdirectories in a directory. '.' and '..' are excluded. The "-r" flag can be used to get all files and subdirectories recursively. The items returned are sorted by name unless the "-no_sort" flag is used. * All() Same as "all('-r')". * all_dirs() Same as "all()", but only return directories. * All_Dirs() Same as "all_dirs('-r')". * all_files() Same as "all()", but only return files. * All_Files() Same as "all_files('-r')". * all_links() Same as "all()", but only return links. * All_Links() Same as "all_links('-r')". * append() Same as print, but sets the file mode to '>>'. * appendf() Same as printf, but sets the file mode to '>>'. * appendln() Same as println, but sets the file mode to '>>'. * autoclose() By default, IO::All will close an object opened for input when EOF is reached. By closing the handle early, one can immediately do other operations on the object without first having to close it. If you don't want this behaviour, say so like this: $io->autoclose(0); The object will then be closed when $io goes out of scope, or you manually call "<$io-"close>>. * autoflush() Proxy for IO::Handle::autoflush() * backwards() Sets the object to 'backwards' mode. All subsequent "getline" operations will read backwards from the end of the file. Requires Uri Guttman's File::ReadBackwards CPAN module. * block_size() The default length to be used for "read()" and "sysread()" calls. Defaults to 1024. * buffer() Returns a reference to the internal buffer, which is a scalar. You can use this method to set the buffer to a scalar of your choice. (You can just pass in the scalar, rather than a reference to it.) This is the buffer that "read()" and "write()" will use by default. You can easily have IO::All objects use the same buffer: my $input = io('abc'); my $output = io('xyz'); my $buffer; $output->buffer($input->buffer($buffer)); $output->write while $input->read; * clear() Clear the internal buffer. This method is called by write() after it writes the buffer. * close() Proxy for IO::Handle::close() * domain() Set the domain name or ip address that a socket should use. * domain_default() The domain to use for a socket if none is specified. Defaults to 'localhost'. * eof() Proxy for IO::Handle::eof() * fileno() Proxy for IO::Handle::fileno() * getc() Proxy for IO::Handle::getc() * getline() Calls IO::File::getline(). You can pass in an optional record separator. * getlines() Calls IO::File::getlines(). You can pass in an optional record separator. * hash() This method will return a reference to a tied hash representing the directory. This allows you to treat a directory like a hash, where the keys are the file names, and the values call lstat, and deleting a key deletes the file. See IO::Dir for more information on Tied Directories. * io_handle() Direct access to the actual IO::Handle object being used. * is_dir() Returns boolean telling whether or not the IO::All object represents a directory. * is_file() Returns boolean telling whether or not the IO::All object represents a file. * is_link() Returns boolean telling whether or not the IO::All object represents a symlink. * is_open() Find out it the IO::All is currently open for input/output. * is_socket() Returns boolean telling whether or not the IO::All object represents a socket. * is_string() Returns boolean telling whether or not the IO::All object represents an IO::String object. * length() Return the length of the internal buffer. * mode() Set the mode for which the file should be opened. Examples: $io->mode('>>'); $io->mode(O_RDONLY); * name() Return the name of the file or directory represented by the IO::All object. * next() For a directory, this will return a new IO::All object for each file or subdirectory in the directory. Return undef on EOD. * open() Open the IO::All object. Takes two optional arguments "mode" and "perms", which can also be set ahead of time using the "mode()" and "perms()" methods. NOTE: Normally you won't need to call open (or mode/perms), since this happens automatically for most operations. * perms() Sets the permissions to be used if the file/directory needs to be created. * port() Set the port number that a socket should use. * print() Proxy for IO::Handle::print() * printf() Proxy for IO::Handle::printf() * println() Same as print(), but adds newline to each argument unless it already ends with one. * read() This method varies depending on its context. Read carefully (no pun intended). For a file, this will proxy IO::File::read(). This means you must pass it a buffer, a length to read, and optionally a buffer offset for where to put the data that is read. The function returns the length actually read (which is zero at EOF). If you don't pass any arguments for a file, IO::All will use its own internal buffer, a default length, and the offset will always point at the end of the buffer. The buffer can be accessed with the "buffer()" method. The length can be set with the "block_size" method. The default length is 1024 bytes. The "clear()" method can be called to clear the buffer. For a directory, this will proxy IO::Dir::read(). * readline() Same as "getline()". * recv() Proxy for IO::Socket::recv() * rewind() Proxy for IO::Dir::rewind() * rmdir() Delete the directory represented by the IO::All object. * seek() Proxy for IO::Handle::seek() * send() Proxy for IO::Socket::send() * shutdown() Proxy for IO::Socket::shutdown() * slurp() Read all file content in one operation. Returns the file content as a string. In list context returns every line in the file. * stat() Proxy for IO::Handle::stat() * string_ref() Proxy for IO::String::string_ref() Returns a reference to the internal string that is acting like a file. * sysread() Proxy for IO::Handle::sysread() * syswrite() Proxy for IO::Handle::syswrite() * tell() Proxy for IO::Handle::tell() * throw() This is an internal method that gets called whenever there is an error. It could be useful to override it in a subclass, to provide more control in error handling. * truncate() Proxy for IO::Handle::truncate() * unlink Unlink (delete) the file represented by the IO::All object. NOTE: You can unlink a file after it is open, and continue using it until it is closed. * unlock Release a lock from an object that used the "-lock" flag. * write Opposite of "read()" for file operations only. NOTE: When used with the automatic internal buffer, "write()" will clear the buffer after writing it. STABILITY The goal of the IO::All project is to continually refine the module to be as simple and consistent to use as possible. Therefore, in the early stages of the project, I will not hesitate to break backwards compatibility with other versions of IO::All if I can find an easier and clearer way to do a particular thing. This is the first revision of this module. IO is tricky stuff. There is definitely more work to be done. On the other hand, this module relies heavily on very stable existing IO modules; so it may work fairly well. I am sure you will find many unexpected "features". Please send all problems, ideas and suggestions to INGY@cpan.org. Known Bugs and Deficiencies Not all possible combinations of objects and methods have been tested. There are many many combinations. All of the examples have been tested. If you find a bug with a particular combination of calls, let me know. If you call a method that does not make sense for a particular object, the result probably won't make sense. No attempt is made to check for improper usage. Support for format_write and other format stuff is not supported yet. SEE ALSO IO::Handle, IO::File, IO::Dir, IO::Socket, IO::String, IO::ReadBackwards Also check out the Spiffy module if you are interested in extending this module. AUTHOR Brian Ingerson COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See