Core PHP 12 programs with output 15 Q/A 5 MCQs

Learning Objectives – after this chapter you will be able to:

  • Open, read, write, append and close files with fopen(), fread(), fgets(), fgetc(), fwrite() and fclose().
  • Use the file modes r, r+, w, w+, a, a+, x and x+.
  • Use the shortcut functions file_get_contents(), file_put_contents() and file().
  • Upload files from a form with $_FILES and move_uploaded_file(), with size and type restrictions.
Working with Files on the Server

One of the most useful features of a server-side language is its ability to work with the file system of the server that hosts the web site. This clearly distinguishes PHP from a client-side language such as JavaScript: JavaScript is sent to the visitor's browser and runs there, while PHP runs on the server and only the result is sent to the browser – so PHP can read and write the server's files. PHP works with both text files and database systems; this chapter covers files, Part IV covers databases.

To access a file you first establish a connection to it by opening it with fopen(). You give two parameters: the name of the file and the mode – how you want to use the file (reading, writing …). fopen() returns a file handle (a resource) that is used by the other file functions.

Opening a File
Syntax
$handle = fopen(filename, mode);
ModeDescription
rRead only. Starts at the beginning of the file.
r+Read/Write. Starts at the beginning of the file.
wWrite only. Opens and clears the contents of the file, or creates a new file if it does not exist.
w+Read/Write. Opens and clears the file, or creates a new one.
aAppend. Opens and writes to the end of the file, or creates a new file if it does not exist.
a+Read/Append. Preserves the file content and writes to the end.
xWrite only. Creates a new file. Returns false and an error if the file already exists.
x+Read/Write. Creates a new file. Returns false and an error if the file already exists.

If fopen() cannot open the file it returns false. The following example shows a message and stops if the file cannot be opened:

File: htdocs/phpbook/ch14/open.php
<html>
<body>
<?php
$file = fopen("welcome.txt", "r") or exit("Unable to open file!");
?>
</body>
</html>
OUTPUT browser · http://localhost/phpbook/ch14/open.php
Warning: fopen(welcome.txt): Failed to open stream: No such file or directory in /opt/lampp/htdocs/phpbook/ch14/open.php on line 4
Unable to open file!

(The warning appears because welcome.txt does not exist yet; exit() then prints the message and ends the script.)

Closing a File

fclose() closes an open file and frees the handle:

$file = fopen("test.txt", "r");
// some code to be executed
fclose($file);
Writing a File – fwrite() and fputs()
Syntax
int fwrite(resource $handle, string $string [, int $length])

fwrite() writes the string to the file and returns the number of bytes written. fputs() is an alias of fwrite(). The example writes text received from a form into welcome.txt:

File: htdocs/phpbook/ch14/writefile.php
<?php
$file = fopen("welcome.txt", "w") or exit("Unable to create file!");
$text = $_POST["text"];
$bytes = fwrite($file, $text);
fclose($file);
echo "$bytes bytes written to welcome.txt";
?>
OUTPUT browser · POST http://localhost/phpbook/ch14/writefile.php (text=Welcome to PHP file handling.%0AThis is the second line.%0AAnd this is the third line.)
84 bytes written to welcome.txt

The same with fputs(), this time appending with mode a:

File: htdocs/phpbook/ch14/append.php
<?php
$file = fopen("welcome.txt", "a") or exit("Unable to open file!");
fputs($file, "\nLine appended on " . date("d-m-Y"));
fclose($file);
echo "Line appended.";
?>
OUTPUT browser · http://localhost/phpbook/ch14/append.php
Line appended.
Checking for End-of-File

feof() checks whether the end of file (EOF) has been reached. It is useful for looping through data of unknown length.

You cannot read from files opened in w, a or x mode!

Reading a File Line by Line – fgets()

fgets() reads a single line from a file. After the call the file pointer has moved to the next line.

File: htdocs/phpbook/ch14/readlines.php
<?php
$file = fopen("welcome.txt", "r") or exit("Unable to open file!");
// Output a line of the file until the end is reached
$n = 1;
while (!feof($file)) {
    echo $n++ . ": " . fgets($file) . "<br>";
}
fclose($file);
?>
OUTPUT browser · http://localhost/phpbook/ch14/readlines.php
1: Welcome to PHP file handling.
2: This is the second line.
3: And this is the third line.
4: Line appended on 22-10-2026
Reading a File Character by Character – fgetc()

fgetc() reads a single character. After the call the file pointer moves to the next character.

File: htdocs/phpbook/ch14/readchars.php
<?php
$file = fopen("welcome.txt", "r") or exit("Unable to open file!");
$count = 0;
while (($c = fgetc($file)) !== false) {
    if ($c == "e") $count++;
}
fclose($file);
echo "The letter 'e' occurs $count times in welcome.txt";
?>
OUTPUT browser · http://localhost/phpbook/ch14/readchars.php
The letter 'e' occurs 11 times in welcome.txt
Reading with fread()
Syntax
string fread(resource $handle, int $length)

fread() reads up to length bytes. Reading stops as soon as length bytes have been read or the end of the file is reached. To read a whole file pass its size, obtained with filesize():

File: htdocs/phpbook/ch14/fread.php
<?php
$file = fopen("welcome.txt", "r") or exit("Unable to open file!");
$text = fread($file, filesize("welcome.txt"));
fclose($file);
echo "<pre>" . htmlspecialchars($text) . "</pre>";
echo "File size: " . filesize("welcome.txt") . " bytes";
?>
OUTPUT browser · http://localhost/phpbook/ch14/fread.php
Welcome to PHP file handling.
This is the second line.
And this is the third line.
Line appended on 22-10-2026
File size: 112 bytes
Shortcut Functions
FunctionPurpose
file_get_contents($f)Reads the whole file into a string.
file_put_contents($f, $data)Writes a string to a file (use FILE_APPEND to append).
file($f)Reads a file into an array – one element per line.
file_exists($f)Checks whether a file or folder exists.
unlink($f)Deletes a file.
copy($a, $b) / rename($a, $b)Copies / renames (moves) a file.
File: htdocs/phpbook/ch14/shortcuts.php
<?php
file_put_contents("visitors.txt", "Asha\nRavi\n");
file_put_contents("visitors.txt", "Neha\n", FILE_APPEND);
echo "Content:<br>" . nl2br(file_get_contents("visitors.txt"));
$lines = file("visitors.txt", FILE_IGNORE_NEW_LINES);
echo "Number of visitors: " . count($lines) . "<br>";
echo "Exists? " . (file_exists("visitors.txt") ? "yes" : "no") . "<br>";
copy("visitors.txt", "backup.txt");
unlink("visitors.txt");
echo "After unlink, exists? " . (file_exists("visitors.txt") ? "yes" : "no");
?>
OUTPUT browser · http://localhost/phpbook/ch14/shortcuts.php
Content:
Asha
Ravi
Neha
Number of visitors: 3
Exists? yes
After unlink, exists? no
A simple hit counter
File: htdocs/phpbook/ch14/counter.php
<?php
$f = "hits.txt";
$hits = file_exists($f) ? (int) file_get_contents($f) : 0;
$hits++;
file_put_contents($f, $hits, LOCK_EX);
echo "This page has been viewed $hits times.";
?>
OUTPUT browser · http://localhost/phpbook/ch14/counter.php
This page has been viewed 3 times.

(The output above is the third visit.)

File Upload

Allowing users to upload files from a form is very useful. Look at the following HTML form for uploading files:

File: htdocs/phpbook/ch14/upload.html
<html>
<body>
<form action="upload_file.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file">
<br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
OUTPUT browser · http://localhost/phpbook/ch14/upload.html
Browser output
  • The enctype attribute of the <form> tag specifies which content type is used when the form is submitted. multipart/form-data is required when a form sends binary data, like the contents of a file.
  • The type="file" attribute of <input> makes the browser show a Browse/Choose File button.
  • The form must use method="post".

Allowing users to upload files is a big security risk. Only permit trusted users to upload, restrict the file type and size, never trust the file name sent by the browser, and never store uploaded files where they could be executed as PHP.

Creating the upload script

By using the superglobal $_FILES array you receive files uploaded from a client computer. The first index is the form's input name and the second index can be:

ElementMeaning
$_FILES["file"]["name"]the original name of the uploaded file
$_FILES["file"]["type"]the MIME type sent by the browser (e.g. image/gif)
$_FILES["file"]["size"]the size of the file in bytes
$_FILES["file"]["tmp_name"]the name of the temporary copy stored on the server
$_FILES["file"]["error"]the error code resulting from the upload (0 = no error)
File: htdocs/phpbook/ch14/upload_file.php
<?php
if ($_FILES["file"]["error"] > 0) {
    echo "Error: " . $_FILES["file"]["error"] . "<br>";
} else {
    echo "Upload: " . $_FILES["file"]["name"] . "<br>";
    echo "Type: " . $_FILES["file"]["type"] . "<br>";
    echo "Size: " . round($_FILES["file"]["size"] / 1024, 2) . " Kb<br>";
    echo "Stored in: " . $_FILES["file"]["tmp_name"];
}
?>
OUTPUT browser · upload_file.php after choosing logo.gif and clicking Submit
Upload: logo.gif
Type: image/gif
Size: 0.83 Kb
Stored in: /tmp/phprNckwr
Restrictions on upload

In this script we add restrictions: the user may only upload .gif or .jpeg files, and the file size must be under 20 KB:

File: htdocs/phpbook/ch14/upload_restrict.php
<?php
if ((($_FILES["file"]["type"] == "image/gif")
  || ($_FILES["file"]["type"] == "image/jpeg")
  || ($_FILES["file"]["type"] == "image/pjpeg"))
  && ($_FILES["file"]["size"] < 20000)) {
    if ($_FILES["file"]["error"] > 0) {
        echo "Error: " . $_FILES["file"]["error"] . "<br>";
    } else {
        echo "Upload: " . $_FILES["file"]["name"] . "<br>";
        echo "Type: " . $_FILES["file"]["type"] . "<br>";
        echo "Size: " . round($_FILES["file"]["size"] / 1024, 2) . " Kb<br>";
    }
} else {
    echo "Invalid file";
}
?>
OUTPUT browser · upload_restrict.php with holiday.jpg (730 KB)
Invalid file

(Old Internet Explorer versions sent JPEG files as image/pjpeg; modern browsers send image/jpeg.)

Saving the uploaded file

The examples above create a temporary copy of the uploaded file in PHP's temp folder (C:\xampp\tmp in XAMPP). The temporary file disappears when the script ends. To keep it we must move it to another location with move_uploaded_file():

File: htdocs/phpbook/ch14/save_upload.php
<?php
$allowed = ["image/gif", "image/jpeg", "image/png"];
if (in_array($_FILES["file"]["type"], $allowed) && $_FILES["file"]["size"] < 20000) {
    if ($_FILES["file"]["error"] > 0) {
        echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
    } else {
        echo "Upload: " . $_FILES["file"]["name"] . "<br>";
        echo "Type: " . $_FILES["file"]["type"] . "<br>";
        echo "Size: " . round($_FILES["file"]["size"] / 1024, 2) . " Kb<br>";
        if (!is_dir("upload")) {
            mkdir("upload");
        }
        $target = "upload/" . basename($_FILES["file"]["name"]);
        if (file_exists($target)) {
            echo $_FILES["file"]["name"] . " already exists.";
        } else {
            move_uploaded_file($_FILES["file"]["tmp_name"], $target);
            echo "Stored in: " . $target;
        }
    }
} else {
    echo "Invalid file";
}
?>
OUTPUT browser · save_upload.php with logo.gif – first upload
Upload: logo.gif
Type: image/gif
Size: 0.83 Kb
Stored in: upload/logo.gif

Uploading the same file a second time:

OUTPUT browser · save_upload.php with logo.gif – second upload
Upload: logo.gif
Type: image/gif
Size: 0.83 Kb
logo.gif already exists.

The script checks whether the file already exists; if not, it moves the file into the upload folder. basename() removes any directory part from the name sent by the browser.

Checking the real file type

$_FILES["file"]["type"] is sent by the browser and can be faked. For important uploads check the content on the server: mime_content_type($_FILES["file"]["tmp_name"]) or getimagesize() for images, and give the stored file a new, safe name.

Upload error codes
ConstantValueMeaning
UPLOAD_ERR_OK0No error, the upload succeeded.
UPLOAD_ERR_INI_SIZE1File exceeds upload_max_filesize in php.ini.
UPLOAD_ERR_FORM_SIZE2File exceeds MAX_FILE_SIZE given in the form.
UPLOAD_ERR_PARTIAL3The file was only partially uploaded.
UPLOAD_ERR_NO_FILE4No file was uploaded.
UPLOAD_ERR_NO_TMP_DIR6The temporary folder is missing.
UPLOAD_ERR_CANT_WRITE7Failed to write the file to disk.
Key Takeaways
  • fopen() opens a file in a mode (r, w, a, x, plus + variants) and returns a handle; fclose() closes it.
  • fwrite()/fputs() write; fgets() reads a line, fgetc() a character, fread() a number of bytes; feof() detects the end.
  • file_get_contents(), file_put_contents() and file() do common jobs in one call.
  • Upload forms need method="post" and enctype="multipart/form-data".
  • $_FILES describes the upload; move_uploaded_file() saves it permanently.
  • Always restrict type and size and never trust the browser-supplied name or type.
Program File

Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch14 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.

Question / Answer (15 questions)

Answer : PHP runs on the server, so it has access to the server's file system; JavaScript runs in the visitor's browser and has no access to the server's files.

Answer : A file handle (resource) used by other file functions, or false if the file cannot be opened.

Answer : r opens for reading from the beginning; w opens for writing and clears the file (creating it if necessary); a opens for writing at the end of the file (creating it if necessary).

Answer : w overwrites an existing file; x creates a new file and fails (returns false with a warning) if the file already exists.

Answer : fwrite() returns the number of bytes written (false on failure). fputs() is an alias of fwrite().

Answer : It returns true when the file pointer has reached the end of the file, so it is used to stop loops that read files of unknown length.

Answer : fgets() reads one line, fgetc() reads one character, and fread($h, $n) reads up to $n bytes.

Answer : With file_get_contents("file.txt"), or with fread($handle, filesize("file.txt")).

Answer : An array containing the lines of the file, one line per element.

Answer : method="post" and enctype="multipart/form-data", plus an <input type="file" name="…"> field.

Answer : name (original file name), type (MIME type), size (bytes), tmp_name (temporary file on the server) and error (error code); PHP 8.1 also adds full_path.

Answer : It stays only as a temporary file in PHP's temp folder and is deleted automatically when the script ends.

Answer : It is supplied by the browser and can be forged. The real content should be checked on the server with mime_content_type(), finfo or getimagesize().

Answer : file_uploads (must be On), upload_max_filesize (size of one file), post_max_size (size of the whole request) and max_file_uploads (number of files).

Answer : UPLOAD_ERR_NO_FILE – the form was submitted without choosing a file.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. Which mode opens a file for writing and erases its existing content?

Show Answer

Correct Answer : C. w
w truncates the file (or creates it).

Q2. Which function reads a single line from a file?

Show Answer

Correct Answer : B. fgets()
fgets() reads one line.

Q3. Which enctype is required for file uploads?

Show Answer

Correct Answer : C. multipart/form-data
Binary file data needs multipart/form-data.

Q4. Which function permanently saves an uploaded file?

Show Answer

Correct Answer : B. move_uploaded_file()
It moves the temporary upload to its final location.

Q5. $_FILES["file"]["tmp_name"] contains:

Show Answer

Correct Answer : B. The temporary path on the server
tmp_name is the server-side temporary copy.

Bibliography/References

The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.

  1. The PHP Group. (n.d.). PHP Manual – fopen. https://www.php.net/manual/en/function.fopen.php
  2. The PHP Group. (n.d.). PHP Manual – Filesystem Functions. https://www.php.net/manual/en/ref.filesystem.php
  3. The PHP Group. (n.d.). PHP Manual – Handling file uploads. https://www.php.net/manual/en/features.file-upload.php
  4. The PHP Group. (n.d.). PHP Manual – Error Messages Explained (uploads). https://www.php.net/manual/en/features.file-upload.errors.php
  5. OWASP Foundation. (n.d.). File Upload Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html