Skip to content
C Basics: Switch an Update Stream Between Reading and Writing

C Basics: Switch an Update Stream Between Reading and Writing

November 1, 2026

An update stream supports both reading and writing, but switching direction requires care. Use positioning calls to overwrite one byte and read the complete result.

Prepare a scratch directory

Tested on Linux amd64 with GCC 14.2.0. Install GCC and make gcc available on PATH. You also need Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. This example uses the C standard library.

Keep the same terminal open. Stop if setup fails, before saving the source:

start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1

Run the example

Save this as update-stream-position-demo.c:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *stream = tmpfile();
    if (stream == NULL) {
        perror("tmpfile");
        return EXIT_FAILURE;
    }
    if (fputs("ABCDE", stream) == EOF || fseek(stream, 2, SEEK_SET) != 0) {
        goto failure;
    }
    int current_byte = fgetc(stream);
    if (current_byte == EOF) {
        goto failure;
    }
    long position = ftell(stream);
    if (position == -1L) {
        goto failure;
    }
    printf("Read: %c; next position: %ld\n", current_byte, position);
    if (fseek(stream, position - 1, SEEK_SET) != 0 ||
        fputc('X', stream) == EOF || fseek(stream, 0, SEEK_SET) != 0) {
        goto failure;
    }
    char result[6] = {0};
    if (fread(result, 1, 5, stream) != 5) {
        goto failure;
    }
    printf("Updated: %s\n", result);
    if (fclose(stream) != 0) {
        perror("fclose");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;

failure:
    fputs("Stream operation failed\n", stderr);
    fclose(stream);
    return EXIT_FAILURE;
}

Compile and run it. The second command runs only after compilation succeeds:

gcc -std=c17 -Wall -Wextra -Werror -pedantic update-stream-position-demo.c -o update-stream-position-demo &&
./update-stream-position-demo

Observed output:

Read: C; next position: 3
Updated: ABXDE

Read the result

Reading C advances the position to three. Seeking back one byte before writing replaces C with X instead of appending. The final seek moves to the beginning and provides the required transition back to input. Each positioning operation is checked.

Apply it carefully

This uses a seekable binary temporary file. Do not assume a pipe or terminal supports seeking. Text-stream positions have portability restrictions; do not perform arbitrary arithmetic on their ftell values. For very large files, POSIX fseeko and ftello avoid the limits of long where appropriate. The temporary file is deleted on close.

The official reference documents the behavior used here.

Clean up

Remove only the source and executable created for this example, then return to the starting directory:

rm -- update-stream-position-demo.c update-stream-position-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directory

If the directory is not empty, inspect its remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on