What if you wanted to read the entire contents of a file, or perhaps analyze it one character at a time. You could do both of these using fread() without too much trouble; for example:
do {$one_char = fread($fp, 1); $counter .= $one_char; } while ($one_char);
However, PHP provides a set of functions that make this sort of thing much more straightforward:
- fgetc()
- feoff()
- fgets()
- fgetcsv()
- fputs()
The fgetc() function can be used to read from files one character at a time.fgetc() takes a single argument, a file handle fp, and returns just one character from the file it points to; it returns False when it reaches the end of the file. This is basically the same as the fread():
$one_char = fgetc($fp)
is equivalent to saying:
$one_char = fread($fp,1)
What if you modify the original hit counter example to use fgetc()? You could have:
<?php
//hit_counter03.php
$counter_file = "./count.dat";
if(!($fp = fopen($counter_file, "r"))) die ("Cannot open $counter_file.");
do {
$one_char = fgetc($fp);
$counter .= $one_char;
} while($one_char);
$counter = (int) $counter;
fclose($fp);
...
You use a while loop to read the entire contents of the data file because fgetc() reads from the file one character at a time. And you need to know when to stop reading, so you assign the last-read character to a dummy variable, and when that's False, you can stop looping. But there's a flaw. As soon as you read either "0" or " " from the file, the loop condition fails and you won't read any more data. If you plan to attract more than nine hits, this is going to be a big problem.
Fortunately, there's another way to do this, using the feof() function.
The feof() function serves a single, simple purpose: it returns True on reaching the end of a specified file (or if an error occurs) and returns False otherwise. It takes just one argument—the relevant file handle:
feof($fp)
So you can use its logical negative as the condition in the loop, to test whether the file position indicator has reached the end of the file:
<?php //hit_counter04.php $counter_file = "./count.dat"; if(!($fp = fopen($counter_file, "r"))) die ("Cannot open $counter_file."); while(!feof($fp)) $counter .= fgetc($fp); $counter = (int) $counter; fclose($fp); $counter++; echo "You're visitor No. $counter."; $fp = fopen($counter_file, "w"); fwrite($fp, $counter); fclose($fp); ?>
The feof() function tells the while statement when to quit (when the end of the file is reached after reading through it character by character with the fgetc() function), and the counter is forced to an integer data type using the (int) statement.
If you use fgetc() to try to read a large file, though, the script's going to take ages to run because it reads only one character at a time. Fortunately, PHP provides fgets() to help you read sets of characters. This function takes two arguments, fp and length, and returns a string of maximum length (length -1) in bytes, as read from the file pointed to by fp. It stops reading for any one of three reasons:
- The specified number of bytes has been read.
- A new line is encountered.
- The end of the file is reached.
The difference between fgets() and fread() is that fgets() stops reading when it reaches end-of-line and reads up to length -1 bytes, while fread() reads past end-of-line and reads up to length bytes. You can apply fgets() to the hit counter like this:
<?php
//hit_counter05.php
$counter_flie = "./count.dat";
if(!($fp = fopen ($counter_file, "r"))) die ("Cannot open $counter_file.");
$counter = (int) fgets($fp, 20);
fclose ($fp);
...
Because the counter needs only one line from the data file, the call to fgets() returns the last counter value, as you want it to.
If you've ever done any work with importing and exporting data, you know about the comma-separated-value (CSV) format for data. (CSV even has its own file extension: .csv.) In CSV files, data values are separated or delimited by commas, and string values are often contained or enclosed within double quotes in between the commas. The fgetcsv() function reads the data in files with the assumption that it is properly formatted in CSV and puts the data it finds in a line into an array. Naturally, once you have an array of data you can easily manipulate it.
The fgetcsv() function must be given a valid file handle, a numerical value higher than the length of each line (including the end-of-line characters), and you can optionally specify data delimiters (the default is comma) and data enclosures (the default is double-quotes). The following code snippet shows how you might retrieve a line of data values from a file in CSV format:
$file_handle = fopen("my_csv_text_file.csv", "r"); $my_data_values_array = fgetcsv($file_handle, 1000, ",");
The result would be an array named $my_data_values_array, and if the first data value in the line of text was someone's first name (Bob, for example) then $my_data_values_array[0] would equal "Bob". Note that a blank line within the text file is treated as a single NULL field, not an error.
The fputs() function is simply an alias for fwrite(); the two are functionally identical.
