Working with Files in PHP, Part Two
by John Coggeshall12/12/2002
Welcome back to PHP Foundations. Last time I
introduced you to the basic file access methods available to PHP:
fopen(), fputs(), and
fgets(). Although very useful, these functions work only with
strings. This week I'll introduce to you more advanced file access
functions that read and write binary files. We'll talk about
fread() (used for reading), fseek() (used to
find specific parts of a given file), along with a few other useful file
access functions.
Basic Binary File I/O
As you may recall from my last column, PHP provides two fundamental
functions for reading and writing text-based data. You'll be happy to know
that when working with binary files, three of the functions you learned
last time are still useful. We'll use fopen() to open our files, fclose() to close them, and fputs() / fwrite() to write data to the appropriate file.
fputs(), although it wasn't discussed earlier, is really
an alias for the function fwrite(). There is no difference
between the two functions; the different names follow the convention
established in other programming languages. If you feel more comfortable
with fputs() instead of fwrite(), use it without
consequence. However, it is good practice to use fwrite()
when dealing with binary data and fputs() for text,
especially if you are doing both at the same time.
|
Related Reading
PHP Cookbook |
Reading Binary data from a file
You'll notice that one function that I am not revisiting this week is
the fgets() function. When working with binary data, you need
a function named fread(). Like fgets(), the
fread() function accepts two parameters:
fread($file_reference, $length);
Note that, unlike fgets(), fread() requires
the $length parameter (the number of bytes to read from the
file) to be specified. Upon success this function will return a string
representation of the binary data read from the file or false (null) upon
failure. How would you use this function to read binary data from a file?
Here's a quick example.
<?php
$fr = fopen('/path/to/myfile.dat', 'r');
$data = fread($fr, 1024);
fclose($fr);
?>
On systems running PHP which differentiate between binary and text
files (such as Windows), you'll need to open the file in binary mode by
including b along with any other modes that you may
require. To read a file on a Windows system using binary mode you'd use
rb instead of the r you'd use on a
UNIX-compatible system. Also, if you have "magic quotes" enabled,
fread() may not function as expected (especially when dealing
with a null character). PHP will automatically convert the "null"
character to its escaped version \0 in the resulting
input. Toggling "magic quotes" can be done by using the
set_magic_quotes_runtime() and
get_magic_quotes_runtime() functions whose information is
available in the PHP manual.
|
Also in PHP Foundations: |
As you might expect, these code snippets read one kilobyte (1024 bytes)
from the file referred to by $fr. Although this works just
fine in a large file of hundreds of thousands (if not millions) of bytes,
it works sequentially. Accessing a specific part of the file would be a
matter of reading and discarding everything up to that point. Writing is
more difficult. For instance, how would you read the 1,432,342nd byte
from a file? What about writing a byte in the middle of a binary file?
Both of these tasks can be solved using the fseek()
function.
Moving the pointer within a file
In order to solve the problem of accessing a specific location within a
file, we'll need a way to adjust the file pointer. What is a file
pointer? It's the marker used by PHP to keep track of where the currently
executing file operations take place. For instance, when a file is first
created the file pointer is adjusted to the beginning of the file.
Likewise, when a file is opened in append mode, the file is opened and the
pointer points to the very end of the file. The fseek()
function allows us to adjust the file pointer to anywhere within the
file.
When using fseek() where the file pointer is placed
(called an offset) is done in reference to one of three different
locations: the beginning of the file, the end of the file, or the current
pointer location. In PHP, these locations are represented by constants as
shown below:
| PHP Constant | File Offset |
SEEK_SET | Starting from the beginning of the file |
SEEK_CUR | Starting from the current pointer location |
SEEK_END | Starting from the end of the file |
To use these constants, we need to understand how the
fseek() function works. Its syntax is
fseek($file_reference, $offset, [$reference_point]);
where $file_reference represents the value returned by
fopen(), and $offset represents the number of
bytes to adjust the file pointer by starting from either
$reference_point, if provided, or SEEK_SET if
omitted. When executed, fseek() returns zero (0) upon success
or negative one (-1) upon failure.
Let's take a look at a few examples. Assume the file being opened exists and is one kilobyte (1024 bytes) in size:
<?php
$fr = fopen('/myfile.dat', 'r');
echo "File opened, pointer is at start of file (SEEK_SET)<BR>";
fseek($fr, 512);
$byte = fread($fr, 1);
echo "The byte is: $byte<BR>";
echo "Pointer is now midway through the file (SEEK_SET+512)<BR>";
fseek($fr, -256, SEEK_CUR);
$byte = fread($fr, 1);
echo "The byte is: $byte<BR>";
echo "Pointer is now a fourth through the file (SEEK_SET+256)<BR>";
fseek($fr, 1024, SEEK_CUR);
$byte = fread($fr, 1);
echo "The byte is: $byte<BR>";
echo "Seek failed, 256+1024 is greater than the file size.
(still at SEEK_SET+256)";
fseek($fr, -1024, SEEK_END);
$byte = fread($fr, 1);
echo "The byte is: $byte<BR>";
echo "Back at start of file. (SEEK_END-1024 equals SEEK_SET)<BR>";
$byte = fread($fr, 1);
echo "The byte is: $byte<BR>";
fclose($fr);
?>
Although here we elected to read from our file, this example could have
been just as easily applied to write data at specific points within the
file by using fputs()/fwrite() instead of
fread().
Determining where the file pointer is
To wrap up today's conversation, let's take a look at one more function
which will tell you where exactly within a file the file pointer is. This
function is called ftell() and has the following syntax:
ftell($file_reference);
This function returns false on error or the current offset of the file pointer starting from the beginning of the file:
<?php
$fr = fopen("/path/to/myfile.dat", 'r');
fseek($fr, rand(1, 1024));
$offset = ftell($fr);
echo "We randomly landed on the $offset byte of the file.<BR>";
?>>
More about Files to come!
That's all I have for you today on files, which are an important part of PHP. By now you've learned how to deal with both binary and text files. In coming issues, I'll be discussing file permissions, directories, and more, so come back soon.
John Coggeshall is a a PHP consultant and author who started losing sleep over PHP around five years ago.
Read more PHP Foundations columns.
Return to the PHP DevCenter.




