PHP Programming/Files

Working with files is an important part of any programming language, and PHP is no different. Whatever your reasons are for wanting to manipulate files, PHP will happily accommodate them through the use of a handful of functions. You should have read and be comfortable with the concepts presented in the first five sections of this book before beginning here.

Folders
To display the current directory: dirname.

To change the directory: chdir.

To make a new directory: mkdir.

fopen and fclose
fopen is the basis for file manipulation. It opens a file in a certain mode (that you specify) and returns a handle. Using this handle you can read or write to the file, before closing it with the fclose function.

Example Usage

In the example above you can see the file is opened for reading by specifying 'r' as the mode. For a full list of all the modes available to fopen, you can look at the PHP Manual page.

Opening and closing the file is all well and good, but to perform useful operations, you need to know about fread and fwrite.

When a PHP script finishes executing, all open files are automatically closed. So although it is not strictly necessary to close a file after opening it, it is considered good programming practice to do so.

Reading
Reading can be done in a number of ways. If you just want all the contents of a file available to work with, you can use the file_get_contents function. If you want each line of the file in an array, you can use the file command. For total control over reading from files, fread can be used.

These functions are usually interchangeable and each can be used to perform each other's function. The first two do not require that you first open the file with fopen or then close it with fclose. These are good for quick, one-time file operations. If you plan on performing multiple operations on a file it is best to use fopen in conjunction with fread, fwrite and fclose as it is more efficient.

An example of using file_get_contents

An example of using file

An example of using fread

As you can see, with these three functions you are able to easily read data from a file into a form that is convenient to work with. The next part shows how these functions can be used to do the jobs of the others, but this is optional. You may skip it and move onto the writing section, if you are not interested.

Writing
Writing to a file is done by using the fwrite function in conjunction with fopen and fclose. As you can see, there aren't as many options for writing to a file as there are for reading from one. However, PHP 5 introduces the function file_put_contents that simplifies the writing process somewhat. This function will be discussed later in the PHP 5 section, as it is fairly self-explanatory and does not require discussion here.

The extra options for writing don't come from the amount of functions, but from the modes available for opening the file. There are three different modes you can supply to the fopen function, if you wish to write to a file. One mode, 'w', wipes the entire contents of the file, so anything you then write to the file will fully replace what was there before. The second mode, 'a', appends stuff to the file so anything you write to the file will appear just after the original contents of the file. The final mode 'x' only works for non-existent files. All three writing modes will attempt to create the file, if it doesn't exist whereas the 'r' mode will not.

An example of using the 'w' mode

An example of using the 'a' mode

An example of using the 'x' mode

Of the three modes shown above, 'w' and 'a' are used the most, but the writing process is essentially the same for all the modes.

Reading and Writing
If you want to use fopen to open a file for both reading and writing all you need to do is put a '+' on the end of the mode. For example, reading from a file requires the 'r' mode. If you want to read and write to/from that file you need to use 'r+' as a mode. Similarly you can read and write to/from a file using the 'w+' mode. However, this will also truncate the file to zero length. For a better description visit the fopen page that has a very useful table describing all the modes available.

Error Checking
Error checking is important for any sort of programming, but when working with files in PHP it is especially important. This need for error checking arises mainly from the filesystem the files are on. The majority of webservers today are Unix-based and so, if you are using PHP to develop web-applications, you have to account for file permissions. In some cases PHP may not have permission to read the file and so, if you've written code to read a particular file, it will result in an ugly error. More likely is that PHP doesn't have permission to write to a file and that will again result in ugly errors. Also, the file's existence is (somewhat obviously) important. When attempting to read a file, you must make sure the file exists first. On the other side of that, if you're attempting to create and then write to a file using the 'x' mode, then you must make sure the file doesn't exist first.

In short, when writing code to work with files, always assume the worst. Assume the file doesn't exist and you don't have permission to read from/write to it. In most cases this means you have to tell the users that, in order for the script to work, they need to adjust those file permissions so that PHP can create files and read from/write to them, but it also means that your script can adjust and perform an alternative operation.

There are two main ways of error checking. The first is by using the '@' operator to suppress any errors when working with the file and then checking, if the result is false or not. The second method involves using more functions like file_exists, is_readable and is_writeable.

Examples of using the '@' operator

Examples of using specific checking functions

You can see by that last example that error-checking makes your code very robust. It allows it to be prepared for most situations and behave accordingly, which is an essential aspect of any program or script.

Line-endings
Line-endings were mentioned briefly in the final example in the 'Reading' section of this chapter and it is important to be aware of them when working with files. When reading from a text file, it is important to know what types of line-endings that file contains. 'Line-endings' are special characters that try to tell a program to display a new line. For example, Notepad will only move a piece of text to a new line, if it finds "\r\n" just before the new line (it will also display new lines, if you put word wrap on).

If someone writes a text file on a Windows system, the chances are that each line will end with "\r\n". Similarly, if they write the file on a Classic Macintosh (Mac OS 9 and under) system, each line will probably end with "\r". Finally, if they write the file on a Unix-based system (Mac OS X and GNU/Linux), each line will probably end with "\n".

Why is this important? Well, when you read a file into a string with file_get_contents, the string will be one long line with those line-endings all over the place. Sometimes they will get in the way of things you want to do with the string so you can remove them with:

Other times you may need to know what kind of line-ending is being used throughout the text in order to be consistent with any new text you add. Luckily, in 99% of cases, the line-endings will never change type throughout the text so the custom function 'detectLineEndings' can be used as a quick way of checking:

Most of the time though, it is just sufficient to be aware of their existence within the text so you can adjust your script to cope properly.

Binary-safe
So far, all of the text seen in this chapter has been assumed to be encoded in some form of plaintext encoding such as UTF-8 or ASCII. Files do not have to be in this format, however, and in fact there exist a huge number of formats that aren't (such as pictures or executables). If you want to work with these files you have to ensure that the functions you are using are 'binary-safe'. Previously you would have to add 'b' to the end of the modes you used to tell PHP to treat the file as a binary file. Failing to do so would give unexpected results and generally 'weird-looking' data.

Since about PHP 4.3, this is no longer necessary as PHP will automatically detect, if it needs to open the file as a text file or a binary file and so you can still follow most of the examples shown here.

Working with binary data is a lot different to working with plaintext strings and characters and involves many more functions that are beyond the scope of this chapter. However, it is important you know about these differences.

Serialization
Serialization is a technique used by programmers to preserve their working data in a format that can later be restored to its previous form. In simple cases this means converting a normal variable such as an array into a string and then storing it somewhere. That data can then be unserialized and the programmer will be able to work with the array once again.

There is a whole chapter devoted to Serialization in this book as it is a useful technique to know how to use effectively. It is mentioned here as one of the primary uses of serialization to store data on plain files when a database is not available. It is also used to store the state of a script and to cache data for quicker access later, and files are one of the preferred media for this storage.

In PHP, serialization is very easy to perform through use of the serialize and unserialize functions. Here follows an example of serialization used in conjunction with file functions.

An example of storing user details in a file so that they can be easily retrieved later.

PHP 5
There is one particular function specific to files that was introduced in PHP 5. That was the file_put_contents function. It offers an alternative method of writing to files that does not exist in PHP 4. To see how it differs, it is easiest to just look at an example.

Examples showing writing to a file in PHP 4 and the equivalent in PHP 5 with the file_put_contents function

file_put_contents is almost always preferable over the fopen method except when performing multiple operations on the same file. It is more preferable to use it for writing than file_get_contents is for reading and for this reason, a function is provided here to emulate the behaviour of file_put_contents for PHP 4: