[ Team LiB ] Previous Section Next Section

Reading from Files

PHP provides a number of functions for reading data from files. These enable you to read by the byte, the line, or even the character.

Reading Lines from a File with fgets() and feof()

After you have opened a file for reading, you often need to access it line by line. To read a line from an open file, you can use fgets(), which requires the file resource returned from fopen() as an argument. You must also pass it an integer as a second argument. This specifies the number of bytes the function should read if it doesn't first encounter a line end or the end of the file. The fgets() function reads the file until it reaches a newline character ("\n"), the number of bytes specified in the length argument, or the end of the file:


$line = fgets( $fp, 1024 ); // where $fp is the file resource returned by fopen()

Although you can read lines with fgets(), you need some way of telling when you have reached the end of the file. The feof() function does this, returning true when the end of the file has been reached and false otherwise. This function requires a file resource as its argument:


feof( $fp ); // where $fp is the file resource returned by fopen()

You now have enough information to read a file line by line, as shown in Listing 11.9.

Listing 11.9 Opening and Reading a File Line by Line
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title> Listing 11.9 Opening and Reading a File Line by Line</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $filename = "test.txt";
12: $fp = fopen( $filename, "r" ) or die("Couldn't open $filename");
13: while ( ! feof( $fp ) ) {
14:   $line = fgets( $fp, 1024 );
15:   print "$line<br/>";
16: }
17: ?>
18: </div>
19: </body>
20: </html>

We call fopen() on line 12 with the name of the file we want to read, using the or operator to ensure that script execution ends if the file cannot be read. This usually occurs if the file does not exist or (on a Unix system) if the file's permissions won't allow the script read access to the file. The actual reading takes place in the while statement on line 14. The while statement's test expression calls feof() for each iteration, ending the loop when it returns true. In other words, the loop continues until the end of the file is reached. Within the code block, we use fgets() on line 14 to extract a line (or 1024 bytes) of the file. We assign the result to $line and then print it to the browser on line 15, appending a <br/> tag for the sake of readability.

Reading Arbitrary Amounts of Data from a File with fread()

Rather than reading text by the line, you can choose to read a file in arbitrarily defined chunks. The fread() function accepts a file resource as an argument, as well as the number of bytes you want to read. It returns the amount of data you have requested unless the end of the file is reached first:


$chunk = fread( $fp, 16 );


Listing 11.10 Reading a File with fread()
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 11.10 Reading a File with fread()</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $filename = "test.txt";
12: $fp = fopen( $filename, "r" ) or die("Couldn't open $filename");
13: while ( ! feof( $fp ) ) {
14:   $chunk = fread( $fp,16 );
15:   print "$chunk<br/>";
16: }
17: ?>
18: </div>
19: </body>
20: </html>

Although fread() enables you to define the amount of data acquired from a file, it doesn't let you decide the position from which the acquisition begins. You can set this manually with the fseek() function, which enables you to change your current position within a file. It requires a file resource and an integer representing the offset from the start of the file (in bytes) to which you want to jump:


fseek( $fp, 64 );

Listing 11.11 uses fseek() and fread() to output the second half of a file to the browser.

Listing 11.11 Moving Around a File with fseek()
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title> Listing 11.11 Moving Around a File with fseek()</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $filename = "test.txt";
12: $fp = fopen( $filename, "r" ) or die("Couldn't open $filename");
13: $fsize = filesize($filename);
14: $halfway = (int)( $fsize / 2 );
15: print "Halfway point: $halfway <br/>\n";
16: fseek( $fp, $halfway );
17: $chunk = fread( $fp, ($fsize - $halfway) );
18: print $chunk;
19: ?>
20: </div>
21: </body>
22: </html>

We calculate the halfway point of our file by dividing the return value of filesize() by 2 on line 14. We can then use this as the second argument to fseek() on line 16, jumping to the halfway point. Finally, we call fread() on line 17 to extract the second half of the file, printing the result to the browser.

Reading Characters from a File with fgetc()

fgetc() is similar to fgets() except that it returns only a single character from a file every time it is called. Because a character is always 1 byte in size, fgetc() doesn't require a length argument. You simply need to pass it a file resource:


$char = fgetc( $fp );

Listing 11.12 creates a loop that reads the file test.txt a character at a time, outputting each character on its own line to the browser.

Listing 11.12 Reading Characters with fgetc()
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 11.12 Reading Characters with fgetc()</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $filename = "test.txt";
12: $fp = fopen( $filename, "r" ) or die("Couldn't open $filename");
13: while ( ! feof( $fp ) ) {
14:  $char = fgetc( $fp );
15:  print "$char<br/>";
16: }
17: ?>
18: </div>
19: </body>
20: </html>
    [ Team LiB ] Previous Section Next Section