Working with files on the server.

In this lecture we'll talk about a topic we need to understand if we want to store data from our HTML forms persistently. PHP provides functions to work with the file system. Using these function we can store data on the server and use stored data to generate HTML pages with PHP scripts. We will discuss only some of rather big list of PHP file functions, but the functions we will discuss are the most commonly used ones.

Opening files.

The most basic function we certainly need to use is fopen() function. The formal description of the function is:
int fopen(file_name, mode)
This function takes two strings as its arguments:
  • name of the file to open
  • and a string indicating how exactly we want the file to be open.
    The mode string may contain one of the following values:
    Value Description
    a Open the file for appending only. Data will be written to the end of the existing file; if the file does not exist, PHP will attempt to create it.
    a+ Open the file for appending and reading. Data will be written to the end of the existing file; if the file does not exist, PHP will attempt to create it.
    r Open the file for reading only.
    r+ Open the file for reading and writing. Data will be written at th beginning of the existing file.
    w Open the file for writing only. Any existing content of the file will be lost. If the file does not exist, PHP will attempt to create it.
    w+ Open the file for writing and reading. Any existing content of the file will be lost. If the file does not exist, PHP will attempt to create it.
    We also need to use "b" in the mode string to deal with binary files.

    Function fopen() returns an integer value by which the open file can be referred to. This integer value is traditionally called file handler. In the case of an error this function returns false. Here is a typical example of fopen() usage:

    $fp = fopen("/some_dir/mydata.db", "wb"); // open binary data file for writing
    if( ! $fp )
       echo "Error: cannot open the file.";
    else{
       // do something with the file content
    }
    
    We also can use HTTP or FTP paths in the file name; that is, we can open a web page or a binary file on another server and work with it as with usual file:
    if( ! ($fp=fopen("http://someserver.net/somepage.html", "r")) ){
       echo "Error: cannot open the file.";
    }
    else{
       // do something with the page
    }
    

    Closing files.

    If a file was successfully opened and we already did everything we wanted to with its content we need to close the file. We need to do it for several reasons. First of all, a file opened for writing may loose some or all data we wrote in it if it's not closed properly. Also if a file is still opened for writing by one process, then it may not be open for writing by another one. That is, if your script didn't close a file, then other users of the same script are not able to open it. To properly close a file we need to use function fclose(). The formal syntax of the function is:
    int fclose(file_handler)
    
    This function takes one argument a file handler of an open file and returns true (1) if it closed it successfully, otherwise it returns false (0).

    Displaying files.

    Now when we know how to open and close files we need to learn what we can do with the content of the files. Probably, the easiest function is fpassthru(). The formal syntax is:
    int fpassthru(filehandler)
    
    This function reads the file from the current position to the very end and prints the content. This function also closes the file when the end of the file is reached. It returns true on success, false on failure. The following example demonstrates a complete PHP script that can open any file on the server or a web page:

    There is another function readfile() that works almost as fpassthru(). The formal syntax is:

    int readfile(file_name)
    
    This function takes name of the file as an argument, opens the file for reading, reads its content, prints it, and closes the file. It returns true on success, false on failure. Using this function the example above can be rewritten as:
    if( ! readfile($_REQUEST["fname"]) )
      echo "Error: cannot open file";
    
    The difference between these functions is:

    Reading from files.

    We may not want to display the entire content of a file. We may only want to read some data from a file and use it in our PHP script. There are several functions to do that. We will discuss only some of them.

    Reading text information.

    First of all there is function fread() that reads one line from the file starting from the current position. As you can see from the definition of the function
    string fgets(file_handler, length)
    
    it takes two arguments file_handler and length. This function will read either length-1 characters from the current position or all the characters till the closest end of the line on the file, whichever comes first. This is the only reason we put this function in the text information section. fgets() returns the string read as the result on success, false on failure. The following example reads three first lines from the file index.html:
    if( $fp = fopen("index.html", "r") ){
       echo "<form> <textarea rows=5 cols=80>";
       echo fgets($fp, 1024);
       echo fgets($fp, 1024);
       echo fgets($fp, 1024);
       echo "</textarea> </form>";
    }
    
    Please notice that function fgets() stops reading from a file when it sees the end of the line even if it read less than length-1 characters.

    Reading binary information.

    If we do not care about end of line symbol, for example, when we read data from a binary file we can use function fread()
    string fread(file_handler, length)
    
    This function reads exactly length characters from the file with the file handler file_handler.
    Note: On systems which differentiate between binary and text files (i.e. Windows) the file must be opened with 'b' included in fopen() mode parameter:
    $filename = "c:\\files\\somepic.gif";
    $fd = fopen($filename, "rb");
    $contents = fread($fd, filesize($filename));
    fclose($fd);
    
    The following example shows how to use these functions in your PHP scripts.

    Recognizing end of file.

    If we read a file piece by piece we need to know when to stop. In other words we need to know if we already reached the end of the file. We can do that using function foef():
    boolean feof(file_handler)
    
    This function takes file handler of an open file as an arguments and returns true if the end of the file has been reached, false otherwise. Usual way to use this function is:
    $fp = fopen("data.txt", "r") or die("Error: cannot open file 'data.txt' for reading");
    while( ! feof($fp) ){
       $str = fgets($fp, 1024);
       // do something with $str
    }
    
    Note: function die() prints the message and terminates the script.

    Reading a whole file.

    If we want to read the whole file and use its content to generate a web page we can use function file():
    array file(filename)
    
    This function takes only one argument the name of the file to be read, reads the file, and puts all its content into an result array. Each element of the returned array contains exactly one line from the file. Upon failure, file() returns false.

    Writing to files.

    Writing to files is done in a very similar way. If we want to write a string in a file we can use either the fputs() or fwrite() function. These two functions are identical. As a matter of fact, fputs() is just an alias for fwrite(). Syntax of the functions is:
    int fputs(file_handler, str_to_write[, length])
    int fwrite(file_handler, str_to_write[, length])
    
    These functions take a file handler of an open file and a string to write into the file. The third argument length is optional. If the length argument is given, writing will stop after length bytes have been written or the end of str_to_write is reached, whichever comes first. The functions return the number of bytes written, or -1 on error.

    We will use the same functions to add some information at the end of the file. If we need to add something to the end we open the file using mode "a". In the example below we open a database file and add information obtained from an HTML form:

    $name = $_POST["name"];
    $phone = $_POST["phone"];
    $addr = $_POST["addr"];
    $zip = $_POST["zip"];
    $fp = fopen("data.db", "a");
    if( !$fp ) die("Error: cannot open file for writing.");
    fputs($fp, "$name\t$phone\t$addr\t$zip\n");
    fclose($fp);
    
    Special symbols \t and \n are used to output tabulation symbol and new line symbol respectively.

    The following code combines read and write functions to create a hit counter for a page:

    Navigating within files.

    When we reading information from a file or writing information to a file we always doing this from the current position. That is, each time we open a file PHP interpreter creates an inner pointer that points somewhere inside the file. Where exactly this pointer points depends on the mode (a, r, or w). Assume we open a file for reading ("r" mode). In this case the pointer will point at the very first character in the file. By running fread($fp, 5) we read 5 characters from the file and move the pointer 5 positions forward. The next time we do reading we'll start from this new position of the pointer. The question is "Can we move the pointer without actually reading data from the file?". Of course, the answer is yes. There are several functions to deal with this inner file pointer:
    int rewind(file_handler)
    int fseek(file_handler, offset[, whence])
    int ftell(file_handler)
    
    All of these functions take file handler as an argument.

    Function rewind() resets the current position of the pointer to the beginning of the file. It returns true on success, false on failure.

    Function ftell() returns the integer number indicating the offset of the pointer from the beginning of the file. In other words, it returns the current position of the pointer.

    Function fseek() moves the current position within the file. The second argument offset indicates the offset of the pointer from the beginning of the file. For example, fseek($fp, 0) does exactly the same thing as rewind(). The third argument whence may take only one of the three possible values:

  • SEEK_SET - default value - Set position equal to offset bytes.
  • SEEK_CUR - Set position to current location plus offset.
  • SEEK_END - Set position to end-of-file plus offset.
    Thus, to move the current position forward by 5 we can run either of the two lines of code:
    fseek($fp, ftell($fp)+5);
    // or
    fseek($fp, 5, SEEK_CUR);
    

    Working with directories.

    PHP also provides a set of functions to deal with directories. We shortly describe some of them;
    dir_halndler opendir(path)
    string readdir(dir_handler)
    void closedir(dir_handler)
    void rewinddir(dir_handler)
    
    Function opendir() takes one string argument the name of the directory to open and returns directory handler on success, false on failure. As directory name we can use
  • "." - the current directory
  • ".." - the parent directory of the current directory
  • "c:/tmp/" - exact name of the directory
    We need to remember the directory handler this function returns because all other directory functions need it.

    Function readdir() reads the next file name from the directory. If there is no more files left it returns false, otherwise it returns the name of the file. Function closedir() closes the directory. The typical way to get to know all files in the current directory would be:

    $dp = opendir(".");
    while( ! ($fname=readdir($dp)) )
       echo "$fname<br>";
    closedir($dir);
    
    Function rewinddir() works very similar to file function rewind() allowing us to get back to the beginning of the directory without closing and reopening it.

    There are several more functions

  • filesize()
  • filemtime()
  • filectime()
  • filetype()
    that provides additional information about a file such as size, modification time, creation time, type of the file by the file name. For more details see example.