++ed by:
SARTAK OALDERS JEEN PHAYLON FIBO

36 PAUSE users
28 non-PAUSE users.

Ingy döt Net

NAME

IO::All - IO::All of it to Graham and Damian!

NOTE

If you've just read the perl.com article at http://www.perl.com/pub/a/2004/03/12/ioall.html, 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;

    # A single statement web server for static files and cgis too
    io(":8080")->accept("-fork")->
      (sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / });

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 = <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;
    use IO::All '-base';
    use IO::All '-tie';
    use IO::All '-lock';

With the exception of '-base', these options are simply defaults that are passed on to every io function within the program.

Options

  • -base

    Boolean. This option inherited from Spiffy, make the current package a subclass of IO::All (which is a subclass of Spiffy). The option is also available to packages that want to use the new subclass as a base class.

        package IO::Different;
        use IO::All '-base';
    • -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. Here we print the contents of a directory:

    perl -MIO::All -le 'print for io(".")->all'

'>' and '<' move data between strings and files:

    $content1 < io('file1');
    $content1 > io('file2');
    io('file2') > $content3;
    io('file3') < $content3;
    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 <DATA>;
    $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,
            '-tie',
           );
                

    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()

  • type()

    Returns a string indicated the type of io object. Possible values are:

        file
        dir
        link
        socket
        string
        pipe

    Returns undef if type is not determinable.

  • 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.

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, Tie::File

Also check out the Spiffy module if you are interested in extending this module.

AUTHOR

Brian Ingerson <INGY@cpan.org>

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 http://www.perl.com/perl/misc/Artistic.html

1 POD Error

The following errors were encountered while parsing the POD:

Around line 1178:

You forgot a '=back' before '=head1'