Input/Output

Introduction

Most programs interact with a computer's file system in some way. Aphiria comes with the FileSystem class to facilitate these interactions. With it, you can easily read and write files, get attributes of files, copy files and folders, and recursively delete directories, and do other common tasks.

File System

For all examples below, assume $fileSystem = new \Aphiria\IO\FileSystem();.

Reading a File

$fileSystem->read(FILE_PATH);

Writing to a File

// The third parameter is identical to PHP's file_put_contents() flags
$fileSystem->write(FILE_PATH, 'foo', \LOCK_EX);

Appending to a File

$fileSystem->append(FILE_PATH, 'foo');

Deleting a File

$fileSystem->deleteFile(FILE_PATH);

Checking if Something is a File

$fileSystem->isFile(FILE_PATH);

Checking if a File is Readable

$fileSystem->isReadable(FILE_PATH);

Checking if a File is Writable

$fileSystem->isWritable(FILE_PATH);

Copying a File

$fileSystem->copy(SOURCE_FILE, TARGET_PATH);

Moving a File

// This is analogous to "cutting" the file
$fileSystem->move(SOURCE_FILE, TARGET_PATH);

Getting a File's Directory Name

$fileSystem->getDirectoryName(FILE_PATH);

Getting a File's Basename

// This returns everything in the file name except for the path preceding it
$fileSystem->getBaseName(FILE_PATH);

Getting a File's Name

// This returns the file name without the extension
$fileSystem->getFileName(FILE_PATH);

Getting a File's Extension

$fileSystem->getExtension(FILE_PATH);

Getting a File's Size

// The size of the file in bytes
$fileSystem->getFileSize(FILE_PATH);

Getting a File's Last Modified Time

$fileSystem->getLastModified(FILE_PATH);

Getting Files in a Directory

// The second parameter determines whether or not we recurse into subdirectories
// This returns the full path of all the files found
$fileSystem->getFiles(DIRECTORY_PATH, true);

Getting Files with Glob

// See documentation for PHP's glob() function
$filesSystem->glob($pattern, $flags);

Checking if a File or Directory Exists

$fileSystem->exists(FILE_PATH);

Creating a Directory

// The second parameter is the chmod permissions
// The third parameter determines whether or not we create nested subdirectories
$fileSystem->createDirectory(DIRECTORY_PATH, 0777, true);

Deleting a Directory

// The second parameter determines whether or not we keep the directory structure
$fileSystem->deleteDirectory(DIRECTORY_PATH, false);

Getting the List of Directories

// The second parameter determines whether or not we recurse into the directories
// This returns the full path of all the directories found
$fileSystem->getDirectories(DIRECTORY_PATH, true);

Copying a Directory

$fileSystem->copyDirectory(SOURCE_DIRECTORY, TARGET_PATH);

Streams

Streams allow you to read and write data in a memory-efficient way. They make it easy to work with large files without crippling your server. PHP has built-in support for streams, but the syntax is clunky, and it requires a bit of boilerplate code to work with. Aphiria wraps PHP's streaming functionality into a simple interface: Aphiria\IO\Streams\IStream (Stream comes built-in).

Here's how you can create a stream:

use Aphiria\IO\Streams\Stream;

$stream = new Stream(fopen('path/to/file', 'r+b'));

Reading from a Stream

You can read chunks of data from a stream via

// Read 64 bytes from the stream
$stream->read(64);

You can also read to the end of a stream via

$stream->readToEnd();

Note: This will read to the end of the stream from the current cursor position. To read the entire stream from the beginning, use (string)$stream.

Writing to a Stream

To write to a stream, call

$stream->write('foo');

Seeking

To seek to a specific point in the stream, call

// Seek to the 1024th byte
$stream->seek(1024);

To rewind to the beginning, you can call

$stream->rewind();

Getting the Length of a Stream

To get the length of a stream, call

$stream->getLength();

If it is not knowable, then getLength() will return null.

Note: If you happen to know the length of the stream ahead of time, you can pass it into the constructor, eg new Stream(fopen('path/to/file', 'r+b'), 2056). If you write anything to the stream, then the length is recalculated.

Copying to Another Stream

Sometimes, you'll need to copy one stream to another. One example would be writing a response body's stream to the php://output stream. You can do this via

$destinationStream = new Stream(fopen('php://output', 'r+b'));
$sourceStream = new Stream(fopen('path/to/file', 'r+b'));
$sourceStream->copyToStream($destinationStream);

Note: Copying to a stream does not rewind the source or destination streams. If you want to write the entire source stream to the destination, then call $sourceStream->rewind() prior to $sourceStream->copyToStream().

Closing a Stream

You can close a stream via

$stream->close();

Note: When PHP performs garbage collection, close() is automatically called by the destructor.

Multi-Streams

In some cases, such as multi-part responses, you may need to append multiple streams together, yet treat them like a single stream. This is where MultiStream comes in handy:

use Aphiria\IO\Streams\MultiStream;
use Aphiria\IO\Streams\Stream;

$multiStream = new MultiStream();
$stream1 = new Stream('php://temp', 'r+');
$stream1->write('foo');
$stream2 = new Stream('php://temp', 'r+');
$stream2->write('bar');
$multiStream->addStream($stream1);
$multiStream->addStream($stream2);
echo (string)$multiStream; // "foobar"