NAME
File::Raw - Fast IO operations using direct system calls
SYNOPSIS
use File::Raw qw(import);
# Slurp entire file
my $content = file_slurp('/path/to/file');
# Write to file
file_spew('/path/to/file', $content);
# Append to file
file_append('/path/to/file', "more data\n");
# Get all lines as array
my $lines = file_lines('/path/to/file');
# Process lines efficiently with callback (line via $_)
file_each_line('/path/to/file', sub {
print "Line: $_\n";
});
# Memory-mapped file access
my $mmap = file_mmap_open('/path/to/file');
my $data = $mmap->data; # Zero-copy access
$mmap->close;
# Line iterator (memory efficient)
my $iter = file_lines_iter('/path/to/file');
while (!$iter->eof) {
my $line = $iter->next;
# process line
}
$iter->close;
# File stat operations
my $size = file_size('/path/to/file');
my $mtime = file_mtime('/path/to/file');
my $exists = file_exists('/path/to/file');
# Type checks
file_is_file('/path/to/file');
file_is_dir('/path/to/dir');
file_is_readable('/path/to/file');
file_is_writable('/path/to/file');
DESCRIPTION
Fast IO operations using direct system calls, bypassing PerlIO overhead. This module provides significantly faster file operations compared to Perl's built-in IO functions.
Performance
The module uses:
Direct read(2)/write(2) syscalls
Pre-allocated buffers based on file size
Memory-mapped file access for zero-copy reads
Efficient line iteration without loading entire file
MULTICALL optimization for callback-based functions
FUNCTIONS
All functions are available with a file_ prefix when imported, e.g. file_slurp, file_spew, etc.
use File::Raw qw(slurp spew);
file_spew('/path/to/file', "data"); # Write data
my $content = file_slurp('/path/to/file'); # Read data
slurp
my $content = File::Raw::slurp($path);
Read entire file into a scalar. Returns undef on error. Pre-allocates the buffer based on file size for optimal performance.
slurp_raw
my $content = File::Raw::slurp_raw($path);
Same as slurp, explicit binary mode.
spew
my $ok = File::Raw::spew($path, $data);
Write data to file (creates or truncates). Returns true on success.
append
my $ok = File::Raw::append($path, $data);
Append data to file. Returns true on success.
lines
my $lines = File::Raw::lines($path);
Returns arrayref of all lines (without newlines).
each_line
File::Raw::each_line($path, sub {
print "Line: $_\n"; # line available via $_
});
Process each line with a callback. Memory efficient - doesn't load entire file into memory.
lines_iter
my $iter = File::Raw::lines_iter($path);
while (!$iter->eof) {
my $line = $iter->next;
}
$iter->close;
Returns a line iterator object for memory-efficient line processing.
Note: For maximum performance, prefer each_line() which uses MULTICALL optimization and is significantly faster. Use lines_iter() when you need iterator control (e.g., early exit, multiple iterators).
mmap_open
my $mmap = File::Raw::mmap_open($path);
my $mmap = File::Raw::mmap_open($path, 1); # writable
Memory-map a file. Returns a File::Raw::mmap object.
File::Raw::mmap methods
- data() - Returns the mapped content as a scalar (zero-copy)
- sync() - Flush changes to disk (for writable maps)
- close() - Unmap the file
size
my $bytes = File::Raw::size($path);
Returns file size in bytes, or -1 on error.
mtime
my $epoch = File::Raw::mtime($path);
Returns modification time as epoch seconds, or -1 on error.
exists
if (File::Raw::exists($path)) { ... }
Returns true if path exists.
is_file
if (File::Raw::is_file($path)) { ... }
Returns true if path is a regular file.
is_dir
if (File::Raw::is_dir($path)) { ... }
Returns true if path is a directory.
is_readable
if (File::Raw::is_readable($path)) { ... }
Returns true if path is readable.
is_writable
if (File::Raw::is_writable($path)) { ... }
Returns true if path is writable.
stat
my $st = File::Raw::stat($path);
Returns a hashref with all file attributes in one syscall. This is much more efficient than calling multiple individual functions.
my $st = File::Raw::stat($path);
# $st = {
# size => 12345,
# mtime => 1234567890,
# atime => 1234567890,
# ctime => 1234567890,
# mode => 0644, # Permission bits only
# is_file => 1,
# is_dir => '',
# dev => 16777233,
# ino => 12345,
# nlink => 1,
# uid => 501,
# gid => 20,
# }
Returns undef if stat fails.
File::Raw caches the last stat result for performance. When you call multiple stat-like functions on the same file (size, mtime, is_readable, etc.), only the first call hits the filesystem.
clear_stat_cache
File::Raw::clear_stat_cache(); # Clear entire cache
File::Raw::clear_stat_cache($path); # Clear cache for specific path
Clear the internal stat cache. Use this when an external process may have modified a file, or to force a fresh stat on the next call.
The cache is automatically invalidated when you use File::Raw functions that modify files (spew, append, unlink, touch, chmod, etc.), but external modifications require manual cache clearing.
my $size1 = File::Raw::size($file); # Cached stat
# External process modifies $file...
File::Raw::clear_stat_cache($file); # Clear cache
my $size2 = File::Raw::size($file); # Fresh stat
copy
my $ok = File::Raw::copy($src, $dst);
Copy a file. Uses native copy functions (copyfile on macOS, sendfile on Linux) for optimal performance. Returns true on success.
move
my $ok = File::Raw::move($src, $dst);
Move/rename a file. Uses rename() for same-filesystem moves, falls back to copy+unlink for cross-device moves. Returns true on success.
unlink
my $ok = File::Raw::unlink($path);
Delete a file. Returns true on success.
touch
my $ok = File::Raw::touch($path);
Create an empty file or update timestamps. Returns true on success.
mkdir
my $ok = File::Raw::mkdir($path);
my $ok = File::Raw::mkdir($path, $mode);
Create a directory. Default mode is 0755. Returns true on success.
rmdir
my $ok = File::Raw::rmdir($path);
Remove an empty directory. Returns true on success.
readdir
my $entries = File::Raw::readdir($path);
Returns arrayref of directory entries (excludes . and ..).
basename
my $name = File::Raw::basename($path);
Returns the filename portion of a path.
dirname
my $dir = File::Raw::dirname($path);
Returns the directory portion of a path.
extname
my $ext = File::Raw::extname($path);
Returns the file extension including the dot (e.g., ".txt").
join
my $path = File::Raw::join($part1, $part2, ...);
Join path components with the appropriate separator. Handles leading/trailing slashes correctly.
my $path = File::Raw::join('/usr', 'local', 'bin');
# Returns: /usr/local/bin
atime
my $epoch = File::Raw::atime($path);
Returns access time as epoch seconds, or -1 on error.
ctime
my $epoch = File::Raw::ctime($path);
Returns inode change time as epoch seconds, or -1 on error.
mode
my $mode = File::Raw::mode($path);
Returns the file permission bits (e.g., 0644), or -1 on error.
is_link
if (File::Raw::is_link($path)) { ... }
Returns true if path is a symbolic link.
is_executable
if (File::Raw::is_executable($path)) { ... }
Returns true if path is executable.
chmod
my $ok = File::Raw::chmod($path, $mode);
Change file permissions. Returns true on success.
File::Raw::chmod($path, 0755);
head
my $lines = File::Raw::head($path); # First 10 lines
my $lines = File::Raw::head($path, 20); # First 20 lines
Returns arrayref of first N lines (default 10).
tail
my $lines = File::Raw::tail($path); # Last 10 lines
my $lines = File::Raw::tail($path, 20); # Last 20 lines
Returns arrayref of last N lines (default 10).
atomic_spew
my $ok = File::Raw::atomic_spew($path, $data);
Write data to a temporary file then atomically rename. This ensures the file is never in a partial state. Returns true on success.
grep_lines
my $lines = File::Raw::grep_lines($path, \&predicate);
my $lines = File::Raw::grep_lines($path, 'not_blank');
Filter lines matching a predicate. The predicate can be a coderef or a registered predicate name.
Built-in predicates: blank, not_blank, empty, not_empty, comment, not_comment
# Using coderef
my $lines = File::Raw::grep_lines($path, sub { /pattern/ });
# Using built-in predicate
my $lines = File::Raw::grep_lines($path, 'not_blank');
count_lines
my $count = File::Raw::count_lines($path);
my $count = File::Raw::count_lines($path, \&predicate);
my $count = File::Raw::count_lines($path, 'not_blank');
Count lines in a file. Optionally filter by predicate.
find_line
my $line = File::Raw::find_line($path, \&predicate);
my $line = File::Raw::find_line($path, 'not_blank');
Find the first line matching a predicate. Returns undef if not found.
map_lines
my $results = File::Raw::map_lines($path, \&transform);
Transform each line with a callback, returns arrayref of results.
my $lengths = File::Raw::map_lines($path, sub { length($_) });
register_line_callback
File::Raw::register_line_callback($name, \&predicate);
Register a custom predicate for use with grep_lines, count_lines, etc.
File::Raw::register_line_callback('has_error', sub { /ERROR/ });
my $errors = File::Raw::grep_lines($path, 'has_error');
list_line_callbacks
my $names = File::Raw::list_line_callbacks();
Returns arrayref of registered predicate names.
HOOKS
File::Raw supports read/write hooks for data transformation.
register_read_hook
File::Raw::register_read_hook(\&hook);
Register a hook that transforms data after reading.
File::Raw::register_read_hook(sub {
my ($path, $data) = @_;
return uc($data); # uppercase all content
});
register_write_hook
File::Raw::register_write_hook(\&hook);
Register a hook that transforms data before writing.
clear_hooks
File::Raw::clear_hooks($phase);
Clear all hooks for a phase. Phase can be: read, write, open, close.
has_hooks
if (File::Raw::has_hooks('read')) { ... }
Check if hooks are registered for a phase.
IMPORT STYLE
use File::Raw qw(:all); # Import all functions as file_*
use File::Raw qw(slurp spew lines); # Import specific functions
use File::Raw qw(import); # Same as :all (backwards compat)
When imported, the functions are installed with `file_` prefix and use custom ops for maximum performance (eliminating function call overhead).
use File::Raw qw(slurp spew);
my $content = file_slurp($path);
file_spew($path, $data);
Available imports: slurp, slurp_raw, spew, append, atomic_spew, lines, exists, size, mtime, atime, ctime, mode, is_file, is_dir, is_link, is_readable, is_writable, is_executable, unlink, mkdir, rmdir, touch, copy, move, chmod, readdir, basename, dirname, extname, clear_stat_cache.
PERFORMANCE NOTES
Platform Optimizations
macOS: Uses copyfile() for native file copying
Linux: Uses sendfile() for zero-copy file transfer
Linux/BSD: Uses posix_fadvise() to hint sequential reads
When to use File::Raw::stat
If you need multiple attributes from a file (size, mtime, is_file, etc.), use File::Raw::stat() instead of calling individual functions:
# SLOW: 5 syscalls
my $size = File::Raw::size($path);
my $mtime = File::Raw::mtime($path);
my $is_file = File::Raw::is_file($path);
# FAST: 1 syscall
my $st = File::Raw::stat($path);
my ($size, $mtime, $is_file) = @{$st}{qw(size mtime is_file)};
AUTHOR
LNATION <email@lnation.org>
BUGS
Please report any bugs or feature requests to bug-file-fast at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=File-Fast. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc File::Raw
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
Search CPAN
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION <email@lnation.org>.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)