Peter Flanigan


File::DataClass::IO - A powerful and concise API to do as much IO as possible


   use File::DataClass::IO;

   # Read the first line of a file and chomp the result
   my $line = io( 'path_name' )->chomp->getline;

   # Write the line to file set permissions, atomic update and fcntl locking
   io( 'path_name' )->perms( oct '0644' )->atomic->lock->print( $line );

   # Constructor methods signatures
   my $obj = io( $obj );            # clone
   my $obj = io( $obj, $hash_ref ); # clone and merge
   my $obj = io( $hash_ref );
   my $obj = io( $name );           # coderef, object ref, arrayref or string
   my $obj = io( $name, $hash_ref );
   my $obj = io( $name, $mode );
   my $obj = io( $name, $mode, $perms );
   my $obj = io( name => $name, mode => $mode, ... );


This is a simplified re-write of IO::All with additional functionality from IO::AtomicFile. Provides the same minimalist API but without the heavy OO overloading. Only has methods for files and directories

Configuration and Environment

File::DataClass::Constants has a class attribute Exception_Class which defaults to File::DataClass::Exception. Set this attribute to the classname used by the "_throw" method

Defines the following attributes;


Defaults to true. Attempts to read past end of file will cause the object to be closed


Defaults to false. Tracks the state of the lock on the underlying file


Defaults to undef. This is set when the object is actually opened


Defaults to false. Set to true when the object is opened


File open mode. Defaults to 'r' for reading. Can any one of; 'a', 'a+', 'r', 'r+', 'w', or 'w+'


Defaults to undef. This must be set in the call to the constructor or soon after. Can be a coderef, an objectref, an arrayref, or a scalar. After coercion to a scalar leading tilde expansion takes place


Boolean defaults to false. Reverse the direction of the sort on the output of the directory listings


Boolean defaults to true. If the IO object is a directory then sort the listings


Defaults to undefined. Set by the "dir" and "file" methods to dir and file respectively. The "dir" method is called by the "next" method. The "file" method is called by the "assert_open" method if the type attribute is undefined


If any errors occur the throw method in the "EXCEPTION_CLASS" in File::DataClass::Constants is called

Methods beginning with an _ (underscore) are deemed private and should not be called from outside this package


Constructs the attribute hash passed to the constructor method. The constructor can be called with these method signatures:

$io = File::DataClass::IO->new( { name => $pathname, ... } )

A hash ref containing a list of key value pairs which are the object's attributes (where name is the pathname, mode the read/write/append flag, and perms the permissions on the file)

$io = File::DataClass::IO->new( $pathname, [ $mode, $perms ] )

A list of values which are taken as the pathname, mode and permissions. The pathname can be an array ref, a coderef, a scalar, or an object that stringifies to a scalar path

$io = File::DataClass::IO->new( $object_ref )

An object which is a File::DataClass::IO


Open the file handle if it is closed and was supplied without a file name


   $path = io( 'path_to_file' )->abs2rel( 'optional_base_path' );

Makes the pathname relative via a call to abs2rel. Returns a path


   $io = io( 'relative_path_to_file' )->absolute( 'optional_base_path' );

Calls "rel2abs" without an optional base path. Returns an IO object ref


   $lines = io( 'path_to_file' )->all;

For a file read all the lines and return them as a single scalar

   @entries = io( 'path_to_directory' )->all( $level );

For directories returns a list of IO objects for all files and subdirectories. Excludes "curdir" in File::Spec and "updir" in File::Spec

Takes an optional argument telling how many directories deep to search. The default is 1. Zero (0) means search as deep as possible The default can be changed to zero by calling the "deep" method

The filter method can be used to limit the results

The items returned are sorted by name unless "sort"(0) is used


   @entries = io( 'path_to_directory' )->all_dirs( $level );

Like ->all( $level ) but returns only directories


   @entries = io( 'path_to_directory' )->all_files( $level );

Like ->all( $level ) but returns only files


   io( 'path_to_file' )->append( $line1, $line2, ... );

Opens the file in append mode and calls "print" with the passed args


   io( 'path_to_file' )->appendln( $line, $line2, ... );

Opens the file in append mode and calls "println" with the passed args


   $io = io( 'path_to_file' )->assert;

Sets the private attribute _assert to true. Causes the open methods to create the path to the directory before the file/directory is opened


   $dir_name = io( 'path_to_file' )->assert_dirpath;

Create the given directory if it doesn't already exist


   $io = io( 'path_to_file' )->assert_filepath;

Calls "assert_dirpath" on the directory part of the full pathname


   $io = io( 'path_to_file' )->assert_open( $mode, $perms );

Calls "file" to default the type if its not already set and then calls "open" passing in the optional arguments


   $io = io( 'path_to_file' )->atomic;

Implements atomic file updates by writing to a temporary file and then renaming it on closure. This method uses the pattern in the _atomic_infix attribute to compute the temporary pathname


   $io = io( 'path_to_file' )->atomic_suffix( '.tmp' );

Syntactic sugar. See "atomix_infix"


   $io = io( 'path_to_file' )->atomic_infix( 'B_*' );

Defaults to B_* (prefix). The * is replaced by the filename to create a temporary file for atomic updates. If the value does not contain a * then the value is appended to the filename instead (suffix). Attribute name _atomic_infix

If the value contains %P it will be replaced with the process id

If the value contains %T it will be replaces with the thread id


   $io = io( 'path_to_file' )->backwards;

Causes "getline" and "getlines" to read the file backwards


   $dirname = io( 'path_to_file' )->basename( @suffixes );

Returns the File::Basename basename of the passed path


   $io = io( 'path_to_file' )->binary;

Sets binary mode


   $io = io( 'path_to_file' )->binmode( $layer );

Sets binmode to the given layer


   $io = io( 'path_to_file' )->block_size( 1024 );

Defaults to 1024. The default block size used by the "read" method


   $bool = io( 'path_to_file' )->boolean;

Returns true if the pathname has been set or the file handle is open, returns false otherwise. The boolean overload calls this


The internal buffer used by "read" and "write"


Returns the pattern that will match against the current or parent directory


   $canonpath = io( '././path_to_file' )->canonpath;

Returns the canonical path for the object


   $io = io( 'path_to_directory' )->catdir( 'additional_directory_path' );

Create a new IO directory object by concatenating this objects pathname with the one that is supplied


   $io = io( 'path_to_directory' )->catfile( 'additional_file_path' );

Create a new IO file object by concatenating this objects pathname with the one that is supplied


   $io = io( 'path_to_file' )->chmod( '0644' );

Changes the permission on the file to the selected value. Permission values can be either octal or string


   $io = io( 'path_to_file' )->chomp;

Causes input lines to be chomped when "getline" or "getlines" are called


   $io = io( 'path_to_file' )->chown( $uid, $gid );

Changes user and group ownership



Set the contents of the internal buffer to the null string



Close the file or directory handle depending on type

If the temporary atomic file exists, renames it to the original filename. Unlocks the file if it was locked. Closes the file handle


   $dest_obj = io( 'path_to_file' )->copy( $destination_path_or_object );

Copies the file to the destination. The destination can be either a path or and IO object. Returns the destination object


   $current_working_directory = io()->cwd;

Returns the current working directory wrapped in a File::DataClass::IO object


   @files = io( 'path_to_root_of_tree' )->deep->all_files

Changes the default level for the "all" methods to zero so that the whole directory tree is searched


Deletes the atomic update temporary file if it exists. Then calls "close"


   $io = io( $tempdir )->delete_tmp_files( $template );

Delete temporary files for this process (temporary file names include the process id). Temporary files are stored in the $tempdir. Can override the template filename pattern if required


If this is an atomic file update calls the "delete" method. If the object is still open it calls the "close" method


   $digest_object = io( 'path_to_file' )->digest( $algorithm, $options );

Returns a Digest object which is calculated from the contents of the specified file. The arguments are optional. The algorithm defaults to SHA-256. The $options hash reference takes the block_size parameter which causes the file to read through the buffer block_size bytes at a time

This was robbed from Path::Tiny


Initialises the current object as a directory


   $dirname = io( 'path_to_file' )->dirname;

Returns the File::Basename dirname of the passed path


   $bool = io( 'path_to_file' )->empty;

Deprecated in favour of "is_empty"


   $io = io( 'path_to_file' )->encoding( $encoding );

Apply the given encoding to the open file handle and store it on the _encoding attribute


Tests to see if the open file handle is showing an error and if it is it "throw"s an eIOError


   $bool = io( 'path_to_file' )->exists;

Returns true if the pathname exists


Initialises the current object as a file


   $filename = io( 'path_to_file' )->filename;

Returns the filename part of pathname


   $dirname = io( 'path_to_file' )->filepath;

Returns the directory part of pathname


   $io = io( 'path_to_directory' )->filter( sub { m{ \A A_ }msx } );

Takes a subroutine reference that is used by the "all" methods to filter which entries are returned. Called with $_ set to each pathname in turn. It should return true if the entry is wanted


   $line = io( 'path_to_file' )->getline;

Asserts the file open for reading. Get one line from the file handle. Chomp the line if the _chomp attribute is true. Check for errors. Close the file if the autoclose attribute is true and end of file has been read past


   @lines = io( 'path_to_file' )->getlines;

Like "getline" but calls "getlines" on the file handle and returns an array of lines

   @lines = io( 'path_to_file' )->head( $no_of_lines );

Returns the first n lines from the file where the number of lines returned defaults to 10. Returns the lines joined with null in a scalar context


   $hex_digest = io( 'path_to_file' )->hexdigest( $algorithm, $options );

Returns a hexadecimal string which is calculated from the "digest" object


Sets default values for some attributes, takes two optional arguments; type and name


   $io = io( 'path_to_file' );

Subroutine exported by default. Returns a new IO object


   $bool = io( 'path_to_file' )->is_absolute;

Return true if the pathname is absolute


   $bool = io( 'path_to_file' )->is_dir;

Tests to see if the IO object is a directory


   $bool = io( 'path_to_file' )->is_empty;

Returns true if the pathname exists and is zero bytes in size


   $bool = io( 'path_to_file' )->is_executable;

Tests to see if the IO object is executable


   $bool = io( 'path_to_file' )->is_file;

Tests to see if the IO object is a file

   $bool = io( 'path_to_file' )->is_link;

Returns true if the IO object is a symbolic link


   $bool = io( 'path_to_file' )->is_readable;

Tests to see if the IO object is readable


   $bool = io( 'path_to_file' )->is_reading;

Returns true if this IO object is in one of the read modes


   $bool = io( 'path_to_file' )->is_writable;

Tests to see if the IO object is writable


   $bool = io( 'path_to_file' )->is_writing;

Returns true if this IO object is in one of the write modes


   $code_ref = io( 'path_to_directory' )->iterator;

When called the coderef iterates over the directory listing. If deep is true then the iterator will visit all subdirectories. If no_follow is true then symbolic links to directories will no be followed. A "filter" may also be applied


   $positive_int = io( 'path_to_file' )->length;

Returns the length of the internal buffer


   $io = io( 'path_to_file' )->lock( $type );

Causes "_open_file" to set a shared flock if its a read and an exclusive flock for any other mode. The type is an enumerated value; FALSE - no locking, LOCK_BLOCKING - blocking flock call (the default), and LOCK_NONBLOCKING - non-blocking flock call


   io( 'path_to_directory' )->mkdir;

Create the specified directory


   io( 'path_to_directory' )->mkpath;

Create the specified path


   $dest_obj = io( 'path_to_file' )->move( $destination_path_or_object );

Moves the file to the destination. The destination can be either a path or and IO object. Returns the destination object


   $io = io( 'path_to_directory' )->next;

Calls "dir" if the type is not already set. Asserts the directory open for reading and then calls "read_dir" to get the first/next entry. It returns an IO object for that entry


   $io = io( 'path_to_directory' )->no_follow;

Defaults to false. If set to true do not follow symbolic links when performing recursive directory searches


   $io = io( 'path_to_file' )->open( $mode, $perms );

Calls either "_open_dir" or "_open_file" depending on type. You do not usually need to call this method directly. It is called as required by "assert_open"


If the _assert attribute is true calls "assert_dirpath" to create the directory path if it does not exist. Opens the directory and stores the handle on the io_handle attribute


Opens the pathname with the given mode and permissions. Calls "assert_filepath" if assert is true. Mode defaults to the mode attribute value which defaults to r. Permissions defaults to the _perms attribute value. Throws eCannotOpen on error. If the open succeeds "set_lock" and "set_binmode" are called


   $parent_io_object = io( 'path_to_file_or_directory' )->parent( $count );

Return "dirname" as an IO object. Repeat $count times


   $pathname = io( 'path_to_file' )->pathname;

Returns then name attribute


   $io = io( 'path_to_file' )->perms( $perms );

Stores the given permissions on the _perms attribute


   $io = io( 'path_to_file' )->print( $line1, $line2, ... );

Asserts that the file is open for writing and then prints passed list of args to the open file handle. Throws ePrintError if the print statement fails


   $io = io( 'path_to_file' )->println( $line1, $line2, ... );

Calls "print" appending a newline to each of the passed list args that doesn't already have one


   $bytes_read = io( 'path_to_file' )->read( $buffer, $length );

Asserts that the pathname is open for reading then calls "read" on the open file handle. If called with args then these are passed to the "read". If called with no args then the internal buffer is used instead. Returns the number of bytes read


   @io_object_refs = io( 'path_to_directory' )->read_dir;
   $io = io( 'path_to_directory' )->read_dir;

If called in an array context returns a list of all the entries in the directory. If called in a scalar context returns the first/next entry in the directory


   $path = io( 'relative_path_to_file' )->rel2abs( 'optional_base_path' );

Makes the pathname absolute. Returns a path


   $relative_path = io( 'path_to_file' )->relative;

Calls "abs2rel" without an optional base path


   $io = io( 'path_to_file' )->reset;

Calls "close" and resets chomp to false


   $io = io( 'path_to_directory' )->rmdir;

Remove the directory


   $number_of_files_deleted = io( 'path_to_directory' )->rmtree;

Remove the directory tree


   $io = io( 'path_to_file' )->seek( $position, $whence );

Seeks to the selected point in the file


   $io = io( 'path_to_file' )->separator( $RS );

Set the record separator used in calls to getlines and chomp


   $io = io( 'path_to_file' )->set_binmode;

Sets the currently selected binmode on the open file handle


   $io = io( 'path_to_file' )->set_lock;

Calls "flock" on the open file handle


   $lines = io( 'path_to_file' )->slurp;
   @lines = io( 'path_to_file' )->slurp;

In a scalar context calls "all" and returns its value. In an array context returns the list created by splitting the scalar return value on the system record separator. Will chomp each line if required


   @directories = io( 'path_to_directory' )->splitdir;

Proxy for "splitdir" in File::Spec


   ($volume, $directories, $file) = io( 'path_to_file' )->splitpath;

Proxy for "splitpath" in File::Spec


   $stat_hash_ref = io( 'path_to_file' )->stat;

Returns a hash of the values returned by a "stat" call on the pathname. Returns undefined if the file does not exist or the file handle is not open


   $io = io( 'path_to_file' )->substitute( $search, $replace );

Substitutes $search regular expression for $replace string on each line of the given file


   @lines = io( 'path_to_file' )->tail( $no_of_lines );

Returns the last n lines from the file where the number of lines returned defaults to 10. Returns the lines joined with null in a scalar context


   $byte_offset = io( 'path_to_file' )->tell;

Returns the byte offset into the file


   $io = io( 'path_to_temp_directory' )->tempfile( $template );

Create a randomly named temporary file in the name directory. The file name is prefixed with the creating processes id and the temporary directory defaults to /tmp


   io( 'path_to_file' )->_throw( 'message', [] );

Exposes the throw method in the exception class


   $io = io( 'path_to_file' )->touch( $time );

Create a zero length file if one does not already exist with given file system permissions which default to 0644 octal. If the file already exists update it's last modified datetime stamp. If a value for $time is provided use that instead if the CORE::time

   $bool = io( 'path_to_file' )->unlink;

Delete the specified file. Returns true if successful


   $io = io( 'path_to_file' )->unlock;

Calls flock on the open file handle with the LOCK_UN option to release the Fcntl lock if one was set. Called by the "close" method


   $io = io( 'path_to_file' )->utf8;

Sets the current encoding to utf8


   $bytes_written = io( 'pathname' )->write( $buffer, $length );

Asserts that the file is open for writing then write the $length bytes from $buffer. Checks for errors and returns the number of bytes written. If $buffer and $length are omitted the internal buffer is used. In this case the buffer contents are nulled out after the write






On MSWin32 and Cygwin platforms there is a race condition when the atomic write option is used. This is caused by the filesystem which does not allow an open file to be renamed

On MSWin32 and Cygwin platforms if the move in atomic write option fails a copy and delete is attempted. This will throw if the copy fails. These platforms deny rename rights on newly created files by default

On MSWin32 and Cygwin platforms binmode is automatically enabled

Bugs and Limitations

There are no known bugs in this module. Please report problems to the address below. Patches are welcome


Larry Wall

For the Perl programming language

Ingy döt Net <>

For IO::All from which I took the API and some tests


Lifted the following features; iterator, tilde expansion, thread id in atomic file name, not following symlinks and some tests


Peter Flanigan, <>

License and Copyright

Copyright (c) 2015 Peter Flanigan. All rights reserved

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic

This program is distributed in the hope that it will be useful, but WITHOUT WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE