如何用C语言低级I/O在文件中插入文本并预留空间?
用底层I/O实现文件中间内容的插入与删除
一、在文件中间插入内容(后移原有内容)
要在文件中间插入新内容,核心逻辑是先暂存插入点后的原有内容,写入新内容后再将暂存内容追加回去,具体步骤如下:
- 打开目标文件:用
open函数以读写模式(O_RDWR)打开文件,确保拥有读写权限。 - 定位插入位置:调用
lseek将文件偏移量移动到要插入内容的起始位置。 - 读取插入点后的内容:用
read函数把插入点到文件末尾的所有内容读取到缓冲区(缓冲区大小需根据文件实际情况调整,大文件需循环读取)。 - 写入新内容:再次调用
lseek回到插入位置,用write写入新内容。 - 回写原有内容:将缓冲区中暂存的原有内容写入到新内容的后方。
- 关闭文件:调用
close释放文件描述符。
示例代码
#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #define BUF_SIZE 4096 // 可根据文件大小调整缓冲区容量 int insert_into_file(const char *filepath, off_t insert_pos, const char *new_content) { int fd = open(filepath, O_RDWR); if (fd == -1) return -1; // 定位到插入位置 if (lseek(fd, insert_pos, SEEK_SET) == -1) { close(fd); return -1; } // 获取原文件末尾位置,计算插入点后内容长度 off_t original_end = lseek(fd, 0, SEEK_END); off_t content_len = original_end - insert_pos; lseek(fd, insert_pos, SEEK_SET); // 读取插入点后内容到缓冲区(大文件需循环读取) char buf[BUF_SIZE]; ssize_t bytes_read = read(fd, buf, content_len); if (bytes_read == -1) { close(fd); return -1; } // 写入新内容 lseek(fd, insert_pos, SEEK_SET); ssize_t bytes_written = write(fd, new_content, strlen(new_content)); if (bytes_written == -1) { close(fd); return -1; } // 回写暂存的原有内容 bytes_written = write(fd, buf, bytes_read); if (bytes_written == -1) { close(fd); return -1; } close(fd); return 0; }
注意事项
- 若插入点后内容超出缓冲区容量,需循环执行
read和后续的write操作,避免数据丢失。 - 必须检查每个系统调用的返回值,处理文件打开失败、读写失败等异常情况。
二、删除文件中间的内容
删除文件中间内容的核心是用删除区域之后的内容覆盖要删除的部分,最后调整文件长度。注:标准截断需用ftruncate,若仅使用给定函数,可通过lseek定位到新末尾后写入0字节(部分系统兼容),以下示例采用更通用的ftruncate方案:
- 打开目标文件:以
O_RDWR模式打开文件。 - 确定删除范围:计算要删除内容的起始位置
del_start、长度del_len,以及删除结束后的位置del_end = del_start + del_len。 - 读取剩余内容:用
lseek定位到del_end,读取后面的所有内容到缓冲区。 - 覆盖删除区域:回到
del_start位置,将缓冲区内容写入,覆盖要删除的部分。 - 截断文件:将文件长度调整为
原长度 - 删除长度。 - 关闭文件:调用
close释放文件描述符。
示例代码
#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #define BUF_SIZE 4096 int delete_from_file(const char *filepath, off_t del_start, size_t del_len) { int fd = open(filepath, O_RDWR); if (fd == -1) return -1; off_t original_len = lseek(fd, 0, SEEK_END); // 检查删除范围是否超出文件边界 if (del_start + del_len > original_len) { close(fd); return -1; } off_t del_end = del_start + del_len; off_t remaining_len = original_len - del_end; // 读取删除区域后的剩余内容 char buf[BUF_SIZE]; lseek(fd, del_end, SEEK_SET); ssize_t bytes_read = read(fd, buf, remaining_len); if (bytes_read == -1) { close(fd); return -1; } // 覆盖删除区域 lseek(fd, del_start, SEEK_SET); ssize_t bytes_written = write(fd, buf, bytes_read); if (bytes_written == -1) { close(fd); return -1; } // 截断文件到新长度 if (ftruncate(fd, original_len - del_len) == -1) { close(fd); return -1; } close(fd); return 0; }
注意事项
- 若无法使用
ftruncate,可尝试lseek(fd, original_len - del_len, SEEK_SET)后调用write(fd, "", 0),但该方法兼容性有限。 - 操作前建议备份文件,避免因异常导致数据损坏。
内容的提问来源于stack exchange,提问作者10969_ shirazu_
相关产品推荐
相关产品推荐

