C Basics: Switch an Update Stream Between Reading and Writing
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 1Run 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-demoObserved output:
Read: C; next position: 3
Updated: ABXDERead 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_directoryIf the directory is not empty, inspect its remaining contents before removing anything else.
Acknowledgements
This post was created with assistance from AI.