Master Linux File I/O: Open, Read, Write, and Advanced Flags Explained
This tutorial walks through Linux file programming fundamentals, covering how to open, create, read, write, and manipulate file descriptors and cursor positions with system calls like open, creat, read, write, lseek, and close, and demonstrates practical examples such as implementing a cp command, editing configuration files, and using both low‑level and standard C library I/O functions.
File Programming Overview
In Linux, everything is represented as a file, including regular files, pipes, sockets, and devices. Programs manipulate files using low‑level system calls to create, open, read, write, seek, and close them.
Opening and Creating Files
The primary system calls are open and creat:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *filename, mode_t mode);Common flags: O_RDONLY – read‑only O_WRONLY – write‑only O_RDWR – read/write
Additional flags control creation and behavior: O_CREAT – create if the file does not exist (requires a mode argument). O_EXCL – fail if O_CREAT is used and the file already exists. O_APPEND – all writes are appended to the end of the file. O_TRUNC – truncate an existing file to zero length when opened for writing.
Reading and Writing
The unbuffered I/O functions are:
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);Example – write a string to a file:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(){
int fd = open("./file", O_RDWR|O_CREAT, 0600);
const char *buf = "test";
write(fd, buf, strlen(buf));
close(fd);
return 0;
}Reading uses the same prototype; it returns the number of bytes read or 0 at EOF.
File Positioning with lseek
lseekmoves the file offset:
off_t lseek(int fd, off_t offset, int whence); whencevalues: SEEK_SET – from the beginning of the file SEEK_CUR – from the current position SEEK_END – from the end of the file
Example – reset cursor to the start:
lseek(fd, 0, SEEK_SET);File Descriptors
Each opened file is identified by a non‑negative integer file descriptor. Standard descriptors are 0 (stdin), 1 (stdout), and 2 (stderr). The kernel maintains internal structures that map a descriptor to the underlying in‑memory representation of the file.
Practical Exercises
1. Simple cp implementation
Use open, read, write, and lseek to copy a source file to a destination file, handling errors and using O_TRUNC to overwrite existing data.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv){
if(argc != 3){
printf("usage: %s src dest
", argv[0]);
exit(1);
}
int src = open(argv[1], O_RDONLY);
if(src == -1){ perror("open src"); exit(1); }
int size = lseek(src, 0, SEEK_END);
lseek(src, 0, SEEK_SET);
char *buf = malloc(size);
read(src, buf, size);
int dst = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0600);
if(dst == -1){ perror("open dst"); exit(1); }
write(dst, buf, size);
close(src); close(dst);
free(buf);
return 0;
}2. Modifying a configuration file
Read the whole file into a buffer, locate a key with strstr, replace the value, reset the cursor with lseek, and write the buffer back.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv){
if(argc != 2){ printf("usage: %s file
", argv[0]); exit(1); }
int fd = open(argv[1], O_RDWR);
int size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
char *buf = malloc(size+1);
read(fd, buf, size);
buf[size] = '\0';
char *p = strstr(buf, "LENG=");
if(p){ p += 5; *p = '6'; }
lseek(fd, 0, SEEK_SET);
write(fd, buf, strlen(buf));
close(fd);
free(buf);
return 0;
}3. Writing integers and structures
Write raw binary data directly with write and read it back with read. Example for a single integer:
#include <fcntl.h>
#include <unistd.h>
int main(){
int fd = open("int.bin", O_WRONLY|O_CREAT|O_TRUNC, 0600);
int value = 100;
write(fd, &value, sizeof(value));
close(fd);
fd = open("int.bin", O_RDONLY);
int read_back;
read(fd, &read_back, sizeof(read_back));
printf("read %d
", read_back);
close(fd);
return 0;
}Structure example:
#include <fcntl.h>
#include <unistd.h>
struct Test{ int a; char c; };
int main(){
int fd = open("struct.bin", O_WRONLY|O_CREAT|O_TRUNC, 0600);
struct Test t = {100, 'a'};
write(fd, &t, sizeof(t));
close(fd);
fd = open("struct.bin", O_RDONLY);
struct Test r;
read(fd, &r, sizeof(r));
printf("a=%d c=%c
", r.a, r.c);
close(fd);
return 0;
}4. Standard C library I/O
The buffered equivalents are fopen, fread, fwrite, fseek, fgetc, fputc, and feof. Mode strings include r, w, a, and their binary variants ( rb, wb, ab). Example:
#include <stdio.h>
#include <string.h>
int main(){
FILE *fp = fopen("text.txt", "w+");
const char *msg = "Hello";
fwrite(msg, 1, strlen(msg), fp);
fseek(fp, 0, SEEK_SET);
char buf[64] = {0};
fread(buf, 1, strlen(msg), fp);
printf("read: %s
", buf);
fclose(fp);
return 0;
}Key Takeaways
Low‑level system calls ( open, read, write, lseek, close) provide unbuffered I/O and work with file descriptors, which are essential for device and socket operations. The standard C library functions ( fopen, fread, fwrite, etc.) add buffering and are convenient for regular file manipulation. Choose the appropriate API based on performance needs, portability, and whether buffering is desired.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
