For advanced tasks like updating specific sections of a large binary file, or ensuring precise control over concurrency (multiple users writing at once), you need to use the traditional file pointer functions for writing.
This process involves: Opening the file in a specific write mode, Writing data with control over the pointer, and Closing the resource.
1. File Write Modes (fopen())
The second argument of fopen() determines both how the file is treated (created or overwritten) and where the pointer starts.
| Mode | Pointer Starts At | File Exists? | File Doesn’t Exist? | Best Use Case |
w (Write) | Beginning | Wiped clean (Zeroed) | Created | Starting a new file or completely overwriting an old one. |
a (Append) | End | Content Preserved | Created | Writing log entries or adding data to the end of a file. |
r+ | Beginning | Content Preserved | ERROR | Reading and writing (updating) content in the middle of a file. |
w+ | Beginning | Wiped clean | Created | Reading and writing, but always starting fresh. |
Example: Starting a Fresh Log File
<?php
$file_path = 'server_messages.log';
// Use 'w' mode: pointer at start, file created if needed, otherwise wiped
$handle = fopen($file_path, 'w') or die("ERROR: Cannot open file in write mode.");
echo "Opened file '$file_path' in write mode (will overwrite if exists).";
?>
2. Writing Data (fwrite())
The fwrite() function writes the specified string to the file stream starting at the current pointer position.
| Function | Purpose |
fwrite(handle, string, length) | Writes the string to the file resource pointed to by handle. Returns the number of bytes written. |
Example: Writing a Simple Entry
<?php
$handle = fopen('data.txt', 'a'); // 'a' mode: pointer starts at the end
$timestamp = date("Y-m-d H:i:s");
$entry = "\n[$timestamp] New user registered.";
// Write the string to the file
$bytes_written = fwrite($handle, $entry);
echo "Wrote $bytes_written bytes to data.txt.";
fclose($handle);
?>
3. Combining Write Modes and fseek()
The real power of file pointers comes when you use a read/write mode (like r+ or w+) with fseek() to update specific bytes without rewriting the whole file.
Example: Updating a Specific Byte Sequence (r+ mode)
Imagine a status file where you only want to update the word “PENDING” to “ACTIVE” without changing anything else.
<?php
$handle = fopen('task_status.txt', 'r+'); // r+: Read and Write, pointer at start, preserve content
// 1. Find the exact position of the text "PENDING" (e.g., using strpos() on the file contents)
// For simplicity, let's assume PENDING starts at byte 100.
$target_byte_position = 100;
// 2. Move the pointer to that specific byte
fseek($handle, $target_byte_position);
// 3. Write the replacement text. It MUST be the exact same length (7 bytes: " ACTIVE")
$new_status = " ACTIVE";
fwrite($handle, $new_status);
echo "Status updated starting at byte 100.";
fclose($handle);
?>
Security Note: File permissions are vital. The directory containing the file must be writable by the PHP process (web server user). You may need to use commands like
chmod 777 directory_nameduring development (though755or775is safer for production).
4. Locking Files (flock())
When multiple users or scripts might try to write to the same file simultaneously, data corruption can occur. File locking prevents this by granting exclusive write access to one script at a time.
| Function | Purpose |
flock(handle, operation) | Applies or releases a lock on a file resource. |
| Operation Constant | Description |
LOCK_EX | Exclusive lock (Write lock). Prevents anyone else from acquiring a lock. |
LOCK_UN | Release lock. |
Example: Safe Concurrent Write
<?php
$handle = fopen('shared_counter.txt', 'c+'); // 'c+' mode is good for creating/reading/writing without wiping
// Attempt to acquire an EXCLUSIVE lock
if (flock($handle, LOCK_EX)) {
// --- ONLY ONE SCRIPT CAN ENTER HERE ---
$current_count = intval(fread($handle, 1024));
ftruncate($handle, 0); // Clear file content
rewind($handle); // Move pointer back to start
$new_count = $current_count + 1;
fwrite($handle, $new_count);
// --- END OF CRITICAL SECTION ---
flock($handle, LOCK_UN); // Release the lock
echo "Counter updated successfully: $new_count.";
} else {
echo "Could not lock file, busy.";
}
fclose($handle);
?>
