Add CSV examples. Flesh out OOP section.
PHP offers so many file functions, the challenge is finding the ones that match your goals.
TuxRadar provides a gentle introduction with good advice, and W3schools provides a handy summary. They might be good to look over before wading through the filesystem functions on php.net.
Create / overwrite a file line-by-line
$fh = fopen( 'myfile.txt' , 'wb' ); // open for write access, binary safe, RETURNS file handle fwrite( $fh , "Here's the first line.\n" ); // write a string, terminate with newline fwrite( $fh , "Here's the second line.\n" ); // this is appended to the file fclose( $fh ) // free up resources
Append to a file line-by-line
(Same as above, but change file mode from 'wb' to 'ab'.)
Read a file line-by-line
$fh = fopen( 'myfile.txt' , 'rb' ); // open for read access, binary safe $line1 = fgets( $fh ); // read a line into a string (\n is included) $line2 = fgets( $fh ); // read the next line fclose( $fh ) // free up resources
Read an entire file
$fh = fopen( 'myfile.txt' , 'rb' ); // open for read access, binary safe $data = fread( $fh , filesize( 'myfile.txt' ) ); // a smaller number reads part of the file fclose( $fh ) // free up resources
fwrite() and fgets() would normally be inside a while, foreach, or for loop.
Use them when you need to parse or manipulate individual lines.
fopen() requires a filespec and a mode.
Create or overwrite an entire file
file_put_contents( $filename , $data ); // create or overwrite file ($data can be string or array)
Append to a file
file_put_contents( $filename , $data, FILE_APPEND ); // append (or create if needed)
Read a file into a string
$s = file_get_contents( $filename ); // read entire file into $s
Read a file into an array
$a = file( $filename ); // $a[0] = line 1, $a[1] = line2 (includes \n)
The examples above need error checking. And sometimes you need to examine a file line-by-line so data can be translated from one form to another.
The following code shows one way to deal with an INI file.
(PHP provides parse_ini_file() to handle this situation, and it can parse multi-dimensional arrays.
But just for kicks.)
Assume MYFILE.INI stores information as: item = value.
First, we need some error checking. We need to make sure fopen() can succeed.
function create_file_handle( $filespec, $mode ) { if ( substr( $mode, -1, 1 ) != 'b' ) $mode .= 'b'; // make mode binary safe, in case it's forgotten if ( $mode == 'rb' && !is_readable( $filespec ) ) { // make sure you can read throw new Exception( "Can't read file."); } else { if ( file_exists( $filespec ) ) { if ( !is_writeable( $filespec ) ) { // make sure you can write throw new Exception( "Can't write to file." ); } } } if ( !$fh = @fopen( $filespec , $mode ) ) { // '@' suppresses warning so you can trap for it throw new Exception( "Problem creating file handle." ); } return $fh; // return file handle }
function array_to_ini_string( $a , $delimiter ) { $s = ""; // create empty string foreach( $a as $k=>$v ) $s .= "$k $delimiter $v\n"; // key = value, append newline return $s; } function ini_file_to_array( $filename , $delimiter ) { $fh = create_file_handle( $filename, 'rb' ); // read-only while ( $line = fgets( $fh ) ) {// get 1 line (includes newline code) $tmparray = explode( $delimiter , $line ); // separate line into 2 array elements $newarray[ trim( $tmparray[0] ) ] = trim( $tmparray[1] ); // create key:value pair } // note: trim() removes extra spaces, tabs, and \n fclose( $fh ); return $newarray; } function dump_file( $title , $filename, $destination = 'web' ) { // simple way to test results $s = "\n----- $title " . strtoupper( $filename ) . " -----\n"; $s .= file_get_contents( $filename ); if ( $destination == 'web' ) { // uses arg w/default value echo nl2br( $s ); // convert \n to breaks } else { echo $s; } }
$filename = 'myfile.ini'; $delimiter = '='; $settings = array( // usually this would be a cleaned $_POST array or parsed INI file 'director_title' => "Advising Coordinator", 'director_name' => "Jim O'Rourke", 'director_uwnetid' => 'jor' ); $mystring = array_to_ini_string( $settings , $delimiter ); // create string from array so it can be written
The next 2 examples accomplish the same thing, using fwrite() and file_put_contents().
Without error checking
$fh = create_file_handle( $filename, 'wb' ); // open to create or overwrite fwrite( $fh, $mystring ); // write it fclose( $fh ); // free up resources $mystring = "hours = 8:00 - 5:00\n"; // create new setting $fh = create_file_handle( $filename, 'ab' ); // open to append fwrite( $fh, $mystring ) ; // append it fclose( $fh );
Without error checking
file_put_contents( $filename , $mystring ); { // create or overwrite $mystring = "hours = 8:00 - 5:00\n"; // create new setting file_put_contents( $filename , $mystring, FILE_APPEND ); { // append it
With error checking and display of results
try { if ( !file_put_contents( $filename , $mystring ) ) { // create or overwrite throw new Exception( 'Write failed.' ); } dump_file( 'CREATED' , $filename ); // add 3rd arg , 'shell' to leave \n unconverted $mystring = "hours = 8:00 - 5:00\n"; // create new setting if ( !file_put_contents( $filename , $mystring, FILE_APPEND ) ) { // append it throw new Exception( 'Append failed.' ); } dump_file( 'APPENDED' , $filename ); } catch( Exception $e ) { echo "\n{$e->getMessage()}\n\n"; }
try { $settings = ini_file_to_array( $filename , $delimiter ); // create associative array from file $settings['director_name'] = "John Williams"; // alter some settings $settings['director_uwnetid'] = 'jw2'; $settings['hours'] = "7:30 - 4:30"; $mystring = array_to_ini_string( $settings , $delimiter ); // create string from array if ( !file_put_contents( $filename , $mystring ) ) { // overwrite throw new Exception( 'Update failed.' ); } dump_file( 'UPDATED' , $filename ); } catch( Exception $e ) { echo "\n{$e->getMessage()}\n\n"; }
A quick summary of useful functions follows:
unlink( 'filespec' ); // unlink() fails if file is open
readfile( 'filespec' ); // get and show file (can't alter content)
$fstring = file_get_contents( 'filespec' ); echo $fstring; // display in a command shell echo nl2br( $fstring ); // display in a web page
$farray = file( 'filespec' ); // each element contains 1 line (including newline code)
$farray = explode( "\n" , $fstring ); $fstring = implode( "" , $farray ); // if array contains newline codes $fstring = implode( "\n" , $farray ); // if array lacks newline codes
foreach( $farray as $v ) { echo $v; // command shell echo nl2br($v); // web }
To add line numbers to display (a variation of TuxRadar's example, see below)
foreach( $farray as $k=>$v ) { // keys will be 0..n echo $k+1 . " : $v" . // command shell echo '<code>' . ($k+1) . '</code> : ' . htmlspecialchars(trim($v)) . "<br />\n"; // web }
Above, ($k+1) forces PHP to create a number before concatenating it with <code>.
htmlspecialchars() prevents a browser from interpreting HTML tags the file might contain.
trim() strips leading / trailing spaces, including newline code at end of each line.
The final \n is optional. It makes the source easier to view with Ctrl-U.
Try it on 'phpinaction.html'.
For functions that get parts of a file, each read advances the file pointer until the end of file is reached.
$line = fgets( $fh ); // get 1 line, including newline code $line = fgetss( $fh ); // strip all HTML tags & PHP code $line = fgetss( $fh , , "<b>,<strong>" ); // strip tags, but allow B and STRONG
$csv_array = fgetcsv( $fh ); // parses fields into array $csv_array[] = fgetcsv( $fh ); // append to 2-dimensional array, good in a loop
$bitofit = fread( $fh, 1024 ); // read 1024 bytes from file $allofit = fread( $fh, filesize( 'filespec' ) ); // read entire file
fseek( $fh , 0 ); // at start of file fseek( $fh , 2048 ); // 2045 bytes into file fseek( $fh , -1024 ); // 1024 bytes from end of file
$char = fgetc( $fh );
$fh = fopen( $filename , 'wb' ); // change mode to 'ab' to append instead fwrite( $fh, 'Hello ' ); // fwrite() expects a string fwrite( $fh, "World!\n" ); // subsequent fwrite's append fclose( $fh ); // file now contains "Hello World!\n"
file_put_contents( 'filespec' , $data ); // $data can be string or array
file_put_contents( 'filespec' , $data, FILE_APPEND );
functions that rely on fopen()
functions that open and close file automatically
functions that get information about files
information about current script : c:\dev\www\dir1\dir2\myscript.php
pathinfo() parses a string into smaller strings.
pathinfo( __FILE__ ) the underlying OS's absolute path to the script.
pathinfo( $_SERVER['SCRIPT_NAME'] ) the web server's path to the script.
Assume this as the current script: c:\dev\www\dir1\dir2\myscript.php
$pathparts = pathinfo( __FILE__ ); // create array, values shown below $pathparts['dirname'] // C:\dev\www\dir1\dir2 $pathparts['basename'] // myscript.php $pathparts['extension'] // php $pathparts['filename'] // myscript
NOTE: PHP allows \\ or // on Windows. Might as well use Unix convention.
Other supported protocols and wrappers.
SplFileObject — massive class for OOP file manipulation
$file = new SplFileObject( 'filespec'); // constructor embeds file handle in object while ( $line = $file->fgets() ) { // hence, don't list it in method, $file already has it echo $line; }