PHP Chapter 10 (Working With Files In PHP)

Working with Files Introduction

The ability to open up files such as plain text or CSV files is a great asset for you as a programmer. Not every job requires a database with multiple tables, and storing simple data in a text file can be a good alternative. Especially if your web host doesn't allow you to have a database!
In this section, we take a look at the various way you can manipulate files with PHP. We'll start by opening a plain text file.
For this section, we'll be using the file called dictionary.txt, which is amongst the ones you downloaded (in the scripts folder).
Open this file up, and take a look at the contents. It should look like this:
AAS = Alive and smiling
ADN = Any day now
AEAP = As early as possible
AFAIK = As far as I know
AFK = Away from keyboard
AKA = Also known as
It's just a long list of values separated by an equals sign. On the left of the equals sign is an abbreviation, and on the right its meaning. We'll open this text file with PHP code. You'll see different ways to open up and work with this text file. Click below to make a start.

Open a File with PHP

To open up a file, there are a few methods you can use. The one we'll start with is readfile( ). As it's name suggest, it reads the contents of a file for you. Try this simple script (this assumes that you've read the short introduction on the previous page).
<?PHP
$file_contents = readfile( "dictionary.txt" );
print $file_contents;
?>
Save the script with any file name your like, but make sure it goes in the same folder as yourdictionary.txt file (see the previous page for an explanation of this file). Run your new code, and see what happens.
You should get a web page full of text, with no separation and no line breaks.
And that's it! Simple, hey? Only two lines of code. You can even get it down to one line:
print readfile("dictionary.txt");
But here's the part that does the reading:
$file_contents = readfile("dictionary.txt");
You start by typing readfile, and then a pair of round brackets. In between the round brackets, type the name of the file you want to open. This can be either direct text, as above, or a variable, like this:
$file_to_read = "dictionary.txt";
print readfile($file_to_read);
You don't have to put the file you're trying to read in the same directory. If you had a folder called files in your directory, you could do this:
$file_to_read = "files\dictionary.txt";
print readfile($file_to_read);
Or have any other file reference you want to use.
The readfile( ) function is useful if all you want to do is open up a file and read its contents.

file_get_contents(file_to_read);

Another function that just reads the contents of a file is file_get_contents( ). It is available in PHP version 4.3 and above. Here's an example:
<?PHP
$file_to_read = "dictionary.txt";
print file_get_contents( $file_to_read );
?>
This used in more or less the same way as the readfile function. The difference for us is the change of name to file_get_contents( ).

The fopen function in PHP

A better method to open files is with fopen( ). This function gives you more options that, such as setting whether the file is for reading only, for writing to as well, and a few more options. Here's an example (this assumes that you've read the short introduction on the previous page):
<?PHP
$file_contents = fopen( "dictionary.txt", "r" );
print $file_contents;
fclose($file_contents);
?>
Run this script and see what happens. You should see something like the following printed out:
Resource id #2
Not quite what you were expecting! The reason is that fopen( ) doesn't actually read the contents of a file. All it does is to set a pointer to the file you want to open. It then returns what's call a file handle. All you're doing is telling PHP to remember the location of the file.
The "r" on the end means "open this file for reading only". We'll see other options in a moment. But now that you've told PHP to remember the location of the file you want to open, how do you read the contents of the file?
One way is to use fgets( ). This will read a specified number of character on a single line of text. It's typically used to loop round and read each line of text. In the example below, we're printing out each line separately. When you're using fgets( ), you also need to check when the end of the file has been reached. This is done with the inbuilt function feof - file, end of file. Try the script out, then we'll explain what's happening:
<?PHP
$file_handle = fopen("dictionary.txt", "r");
while (!feof($file_handle)) {
$line_of_text = fgets($file_handle);
print $line_of_text . "<BR>";
}
fclose($file_handle);
?>
What you should find is that the contents are printed out on separate lines. But how does it work?
The first line is this:
$file_handle = fopen( "dictionary.txt", "r" );
What we're doing here is asking PHP to open up a file, and remember the location. The location is stored as a file handle. We're putting this into a variable called $file_handle. So we haven't yet read the contents of the file – we've just asked PHP to remember where it is.
The next line is tricky! It's a while loop:
while ( !feof( $file_handle ) ) {
}
There's really two parts to this. There's the while loop:
while () {
}
And then there's the condition for the while loop:
!feof( $file_handle )
A while loop, remember, just goes round and round until you tell it to stop. It goes round and round while a condition is true. The condition between the round brackets was our strange !feof line.
The function feof( ) means "file end of file". It tells PHP when the end of a file has been reached. You put the file between the round brackets of the function:
feof( $file_handle )
This means, end of the file referred to in the variable called $file_handle. Except, we've used the NOT operator ( ! ):
!feof( $file_handle )
That's because we want to keep looping while the end of the has NOT been reached:
while ( !feof( $file_handle ) ) {
}
This whole line, then, reads: "While the end of the file has NOT been reached, loop round the file pointed to in $file_handle." As soon as the end of the file has been reached, the while loop will end.
Inside the while loop, the first line is this:
$line_of_text = fgets( $file_handle );
We're using the fgets( ) function to get a line of text from our file. Again, we need the file handle:
fgets( $file_handle );
So we get a line of text from our file, and then place the line into a variable. We then print out the line of text:
print $line_of_text . "<BR>";
As well as printing out the line of text, we're adding a HTML line break.
The last line in the code is this:
fclose( $file_handle );
All this does is to close the open file. It tells PHP that the pointer to the file is no longer needed. You should always close files that you have opened with fopen().
The code is a bit tricky, when you're meeting it for the first time. But this kind of file opening is useful when you need to read each line of text. With our file, for example, we could separate each half of the line. We might want to put the abbreviations into one list box and the meanings into another.
Another point to bear in mind about fgets is that it can take (and often does) a second argument – the size of the line to read:
fgets($file_handle, line_size);
The line size needs to be in bytes. The default is 1024. But this line size is only optional in PHP version 4.2 and above. If your version is earlier than this, then you may get an error if you miss out the line size:
fgets($file_handle, 1024);
If you're really packing a lot of information into each line, then just increase the number for line size.

PHP fopen options

In the code from the previous page, we used fopen and to get at our file. But we were only reading the file. That's was why we had the letter "r" in the round brackets of fopen:
$file_handle = fopen("dictionary.txt", "r");
But there are other options. Here's a fuller list of things you can replace "r" with.
Options for the fopen function in PHP
So if you wanted to read and write to the file, you'd use this:
$file_handle = fopen("dictionary.txt", "r+");
Or this, if you want to append data to the end of file when you're writing it back:
$file_handle = fopen("dictionary.txt", "a+");
If you need to work with binary files (like images), then you can add the "b":
$file_handle = fopen("dictionary.txt", "rb");

Checking if the file exists

It's a good idea to check if the file exists, before trying to do something with it. The file_exists( ) function can be used for this:
if ( file_exists( "dictionary2.txt" ) ) {
print "file exists";
}
else {
print "file doesn't exist";
}
In between the round brackets of file_exists( ) you then type name of your file. If it does exist, then you can go ahead and do something with it; if not, you can write code to handle any errors.

Writing to files in PHP

When you need to write to files, there are some more functions you need to use. If you have a version of PHP below version 5, then you can use the fwrite() function. But you first need to use fopen( ) to get a file handle.
In the next script, we'll try to write some text to a file. We'll use the "w" option, as this will create a file for us, if we don't have one with the filename chosen.
<?PHP
$file_handle = fopen("testFile.txt", "w");
$file_contents = "Some test text";
fwrite($file_handle, $file_contents);
fclose($file_handle);
print "file created and written to";
?>
The new line is the blue coloured one. First we ask PHP to open the file and create a file handle:
$file_handle = fopen("testFile.txt", "w");
So we're asking PHP to create a file handle that points to a text file called "testFile.txt". If a file of this name can't be found, then one will be created with this name. After a comma, we've typed "w". This tells PHP that the file will be write only.
The third line is where we write to the file:
fwrite( $file_handle, $file_contents );
In between the round brackets of fwrite( ), we've placed two things: the file we want to write to, and the contents of the file. And, except for closing the file, that's all you need!
To test to see if it works, run the script. Then look in the folder where you saved the script to. There should now be a file called testFile.txt.

Exercise
Change the "w" into "a". Run your script a few times, then open the text file. What did you notice?

Exercise
Change the "a" into "r". Run your script again, then open the text file. What did you notice? Did the contents of the text file change?

file_put_contents( )

If you have PHP 5, you can use the new function file_put_contents( ) instead of fwrite( ).
It is used in the same way, but has an optional third parameter:
file_put_contents($file_handle, $file_contents, context);
The context option can be FILE_USE_INCLUDE_PATH, FILE_APPEND, LOCK_EX.
So to append to the file, just do this:
file_put_contents($file_handle, $file_contents, FILE_APPEND);

CSV files and PHP

CSV is a type of file. It means Comma Separated Values. Spreadsheets software like Excel will offer you the opportunity to save files with the CSV extension. We'll see how to work with these types of files now.
The image below shows an Excel spreadsheets. It's just a simple price list:
An Excel price list
The next image shows the spreadsheet being saved as a CSV file:
Save As a CSV file
And here's what the data looks like in a text editor:
A CSV file in a text editor
The above CSV file is the one we want to work with. It shows each line separated by commas.
PHP has a function that allows you to work with CSV file. It's called fgetcsv( ). It's just like the fgetsfunction you used earlier. The difference is that fgetcsv( ) separates each line on the commas, and puts each part into an array. Before trying the next code, make sure you copy the widgets.csv file, from the ones you downloaded, over to the same folder where your script is. The widgets.csv file is in the scripts folder. Here's the code:
<?PHP
$file_handle = fopen("widgets.csv", "r");
while (!feof($file_handle) ) {
$line_of_text = fgetcsv($file_handle, 1024);
print $line_of_text[0] . $line_of_text[1]. $line_of_text[2] . "<BR>";
}
fclose($file_handle);
?>
When you run the script, you should see all the lines of text printed out. Here's how it works.
The first two lines you've already met: get a handle to the file you want to open, then create a while loop to loop round it.
$file_handle = fopen("widgets.csv", "r");
while ( !feof($file_handle) ) {
}
Inside the while loop, though, we have our fgetcsv line:
$line_of_text = fgetcsv( $file_handle, 1024 );
In between the round brackets of fgetcsv, we've typed to things: our file handle, and the size of the line to read. The size, in this case, is 1024 - 1 kilobyte. You can change this value. When the function gets the line of text, it puts it into the variable we've called $line_of_text.
But $line_of_text will now be an array. Each line of our text file looks like this:
Widget1, blue, £10
The fgetcsv function will split this line when it sees the comma. It then creates a position in the array to hold each part of the line. So it will set up an array with three positions, in our case. Those positions will be as follows:
$line_of_text[0]
$line_of_text[1]
$line_of_text[2]
To print it all out, we had a this line:
print $line_of_text[0] . $line_of_text[1]. $line_of_text[2] . "<BR>";
All we're doing here is to print out what is in each position of the array. We've then added a HTML line break, just for display purposes.
If you have CSV files from a spreadsheet that you need to display on a web page, the fgetcsvfunction can come in quite handy!

Text Files and Arrays in PHP

There is another option you can use to place lines of text into an array. In the technique below, we're using the explode( ) string function to create an array from each line of text. Here's the code (this assumes that you've been following along from the previous sections):
<?PHP
$file_handle = fopen("dictionary.txt", "rb");
while (!feof($file_handle) ) {
$line_of_text = fgets($file_handle);
$parts = explode('=', $line_of_text);
print $parts[0] . $parts[1]. "<BR>";
}
fclose($file_handle);
?>
The lines to examine are in blue; the rest you have met before (get a file handle, loop round, usefgets to read the line). The first line to note is this:
$parts = explode( '=', $line_of_text );
If you remember the string section, you'll also be familiar with the explode function. It splits a line of text, based on whatever you have provided for the separator. In our code, we have used the equals sign ( = ) as a separator. This is because each line in the dictionary.txt file looks like this:
AAS = Alive and smiling
When the explode function is executed, the variable called $parts will be an array. In our text file there will only be two positions in the array, one for each half of the equals sign.
We then print out both parts of the array with this:
print $parts[0] . $parts[1]. "<BR>";
So $parts[0] will hold the abbreviation (AAS) and $parts[1] will hold the meaning.
The next time round the while loop, the second line will be read from the text file. Exactly the same thing happens, so the line will be split again, and placed into an array. This is a good technique to use, if you want to split each line and do something different with each part of the line.

Paths and Directories in PHP

There are a few inbuilt PHP functions you can use to find out file paths. This is useful for finding the exact location (relative or absolute) of your scripts or pages. Here's a few example. Before you try these out, create a new PHP page and save it as fileDir.php.

Get the Absolute Path of a File
<?PHP
$absolute_path = realpath("fileDir.php");
print "Absolute path is: " . $absolute_path;
?>
To get the exact path of file, then, you can use realpath(). In between the round brackets of the function, type the name of the file.

Get the Directory, but not the file name
<?PHP
$dir = dirname("folder/myphp/fileDir.php");
print "directory is: " . $dir . "<BR>";
?>
To get the names of the folders, you can use the dirname( ) function. This will strip off the name of the file and return the rest of the text between the round brackets of the function.

Get the Filename only
<?PHP
$bas = basename("folder/myphp/fileDir.php");
print "File Name is: " . $bas . "<BR>";
?>
If you only need to get at the name of the file, then use the basename( ) function. When you type a longer file path in between the round brackets of the function, it will strip off the rest and leave the name of the file.
Final Note
Careful when allowing users to upload files from external sources. This could be used to attack your site. There are a few security implication when working with files. For a more in-depth discussion on this, and other security issues, these links are quite useful:
In the next section, we'll move and have a look at how to work with dates and times.

Comments