Broad Network


Handling Characters in PHP File Streams

Files and Directories with Security Considerations in PHP - Part 2

Foreword: In this part of the series, I explain how to manipulate characters in a PHP file stream.

By: Chrysanthus Date Published: 19 Jan 2019

Introduction

This is part 2 of my series, Files and Directories with Security Considerations in PHP. In this part of the series, I explain how to manipulate characters in a PHP file stream. You should have read the previous part of the series before reaching here, as this is the continuation.

Resource
In order for you to use a file in the hard disk or some other drive, you have to do what is called opening the file. For this, the content of the file is copied into memory. This area in memory that has the content of the file is called a stream (precisely a buffer). Whatever you want to do to the file (modifying the file, adding text to the end of the file, or just reading the file) you do to the stream. After that you have to do what is called closing the file.  When a file is closed, the content of the stream is copied to the file in the disk, if necessary. Any modification of stream content or adding of text to the end of the stream is reflected in the file in the disk after closing.

A file may not exist in the disk. This means you have to create it. For this purpose, you still have to use the opening process (see below). A stream for the newly (not existing) opened file is created. You send information to the stream. When you close the file, effectively closing the stream, the content of the stream is copied to the disk. Closing a file means putting an end to the association between the stream and the corresponding file in the disk, after the content of the stream has just been copied to the file, which might or might not have existed, in the disk.

Note: the content of the stream is the file content copied from disk, if the file existed in the disk before it was opened. While you are editing a file, the content may also be saved. Before you close, you can force the saving by flushing; see below.

In order to open, edit and close a file, you need what is known as a resource. A resource is a special kind of reference holding variable. There are different kinds of resources - see later.

You open and close a file to manipulate characters just as you open and close to manipulate lines of text.

Modes
The opening and closing file modes ('r','w','a', etc.) for handling characters are the same as the modes for handling lines of text.

Functions to use
The fputs() Function
The syntax for this function is:

    int fputs ( resource $handle , string $string [, int $length ] )

fputs() writes the contents of string to the file stream pointed to by handle.
fputs() returns the number of bytes written, or FALSE on error.
Note: Putting to a network stream may end before the whole string is written. Return value of fputs() may be checked.
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.
Note: If handle was fopen()ed in append mode, fputs()s are atomic (unless the size of string exceeds the filesystem's block size, on some platforms, and as long as the file is on a local filesystem). That is, there is no need to flock() a resource before calling fputs(); all of the data will be written without interruption.
Note: If writing twice to the file pointer, then the data will be appended to the end of the file content.

The fgetc() Function
The syntax is:

    string fgetc ( resource $handle )

Gets the next character from the given file pointer.

Returns a string containing a single character read from the file pointed to, by handle. Returns FALSE on EOF (end-of-file).

Warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE. Use the === operator for testing the return value of this function.

The fseek() Function
The syntax is:

    int fseek ( resource $handle , int $offset [, int $whence = SEEK_SET ] )

Sets the file position indicator for the file referenced by handle. The new position, measured in bytes from the beginning of the file, is obtained by adding offset to the position specified by whence.

whence values are:
    SEEK_SET - 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.

In general, it is allowed to seek past the end-of-file; if data is then written, reads in any unwritten region between the end-of-file and the sought position will yield bytes with value 0. However, certain streams may not support this behavior, especially when they have an underlying fixed size storage.

Upon success, returns 0; otherwise, returns -1.

Note: If you have opened the file in append (a or a+) mode, any data you write to the file will always be appended, regardless of the file position, and the result of calling fseek() will be undefined.
Note: Not all streams support seeking. For those that do not support seeking, forward seeking from the current position is accomplished by reading (fgetc) and discarding data; other forms of seeking will fail.

The ftell() Function
The syntax is:

    int ftell ( resource $handle )

Returns the position of the file pointer referenced by handle as an integer; i.e., its offset into the file stream.
If an error occurs, returns FALSE.

Note: Because PHP's integer type is signed and many platforms use 32bit integers, some filesystem functions may return unexpected results for files which are larger than 2GB.

The ftruncate() Function
The syntax is:

    bool ftruncate ( resource $handle , int $size )

Takes the file pointer, handle, and truncates the file to length, size.
Returns TRUE on success or FALSE on failure.

Note: If size is larger than the file then the file is extended with null bytes. If size is smaller than the file then the file is truncated to that size.

The fflush() Function
The syntax is:

    bool fflush ( resource $handle )

This function forces a write of all buffered output to the resource pointed to by the file handle.

Returns TRUE on success or FALSE on failure.

The feof() Function
The syntax is:

    bool feof ( resource $handle )

Tests for end-of-file on a file pointer.
Returns TRUE if the file pointer is at EOF or an error occurs (including socket timeout); otherwise returns FALSE.

Warning: If a connection opened by fsockopen() wasn't closed by the server, feof() will hang. To workaround this, see later.
Warning: If the passed file pointer is not valid you may get an infinite loop, because feof() fails to return TRUE.

The rewind() Function
The syntax is:

    bool rewind ( resource $handle )

Sets the file position indicator for handle to the beginning of the file stream.

Returns TRUE on success or FALSE on failure.

Note: If you have opened the file in append ("a" or "a+") mode, any data you write to the file will always be appended, regardless of the file pointer position.

Writing a File
The following code creates a new file and writes characters of text to it.

<?php

    if (!$handle = fopen('temp2.txt', 'w'))
        {
            echo "Cannot open file 'temp2.txt'";
        }
    else
        {
            if (fputs($handle, "A") === false)
                {
                    echo "Cannot write A to temp2.txt.";
                }
            if (fputs($handle, "B") === false)
                {
                    echo "Cannot write B to temp2.txt.";
                }
            if (fputs($handle, "C") === false)
                {
                    echo "Cannot write C to temp2.txt.";
                }
            if (fputs($handle, "D") === false)
                {
                    echo "Cannot write D to temp2.txt.";
                }
            if (fputs($handle, "E") === false)
                {
                    echo "Cannot write E to temp2.txt.";
                }

            echo 'Data written';

            fclose($handle);

        }

?>

The file content is:

    ABCDE

The expression,

    $handle = fopen('temp2.txt', 'w')

results in $handle, which is either the resource or false. If it is false, then !$handle is not a resource. Note the mode that has been used in the above code.

Reading a File
The following code opens and reads the characters of text from a file:

<?php

    if (!$handle = fopen('temp2.txt', 'r'))
        {
            echo "Cannot open file 'temp2.txt'";
        }
    else
        {
            while (($char = fgetc($handle)) !== false)
                {
                    echo $char;
                }

            fclose($handle);

        }

?>

The output is:

    ABCDE

Note the mode that has been used in the above code. The expression,

    $char = fgetc($handle)

results in $buffer, which either has the character or "false". It is compared to false with the Not Identical operator. The while-loop reads characters of text until the end-of-file. After the reading of each character, the file pointer points to the next character.

Appending to a File
"Append" means add characters to the bottom. The following code appends a sixth character to the file, temp2.txt :

<?php

    if (!$handle = fopen('temp2.txt', 'a'))
        {
            echo "Cannot open file 'temp2.txt'";
        }
    else
        {
            if (fputs($handle, "F") === false)
                {
                    echo "Cannot write F to temp2.txt";
                }

            echo 'Data written';

            fclose($handle);

        }

?>

Note the mode that has been used in the above code. The file content becomes,

ABCDEF

Editing a File
To edit a file, open the file in the 'r+' mode. You can change the character, while it is read. The following code illustrates this, changing the fourth (next) character:

<?php

    if (!$handle = fopen('temp2.txt', 'r+'))
        {
            echo "Cannot open file 'temp2.txt'";
        }
    else
        {
            while (($char = fgetc($handle)) !== false)
                {
                    if ($char === "C")
                        {
                            echo $char;
                            fseek($handle, 0, SEEK_CUR);
                            $char = "4";
                            fputs($handle, $char);
                            echo $char;
                        }
                     else
                         {
                             echo $char;
                         }
                }

            fflush ($handle);

            fclose($handle);
        }

?>

Whenever a character is read, this particular seek call is such that it points to the next character.

The old file content was,

    ABCDEF

The new file content is,

    ABC4EF

D was replaced by 4 . Note the use of the fflush() function, in the code.

We have seen a lot, let us take a break here, and continue in the next part of the series.

Chrys


Related Links

Basics of PHP with Security Considerations
White Space in PHP
PHP Data Types with Security Considerations
PHP Variables with Security Considerations
PHP Operators with Security Considerations
PHP Control Structures with Security Considerations
PHP String with Security Considerations
PHP Arrays with Security Considerations
PHP Functions with Security Considerations
PHP Return Statement
Exception Handling in PHP
Variable Scope in PHP
Constant in PHP
PHP Classes and Objects
Reference in PHP
PHP Regular Expressions with Security Considerations
Date and Time in PHP with Security Considerations
Files and Directories with Security Considerations in PHP
Writing a PHP Command Line Tool
PHP Core Number Basics and Testing
Validating Input in PHP
PHP Eval Function and Security Risks
PHP Multi-Dimensional Array with Security Consideration
Mathematics Functions for Everybody in PHP
PHP Cheat Sheet and Prevention Explained
More Related Links

Cousins

BACK NEXT

Comments