C语言修改文件中STORAGE_后序列号写入报错问题咨询
C语言修改文件中STORAGE_后序列号写入报错问题咨询
嘿,我来帮你排查这个写入报错的问题!你当前的代码在读取并处理行内容时是正常的,但一启用fputs写入就出问题,核心原因是**r+模式下读写指针的处理逻辑错误**,加上直接原地修改文件的潜在风险,具体拆解如下:
问题根源
- 读写指针不同步:
r+模式下文件的读、写指针是共享的。你用fgets读取一行后,指针已经移动到下一行开头,这时调用fputs会把内容写到当前指针位置(也就是下一行),而非覆盖原来的目标行,直接导致文件内容混乱,甚至触发文件访问错误。 - 行长度变化的隐患:原行格式是
"STORAGE_7253":,处理后变成"STORAGE_1":,长度明显变短,原行剩余的字符(比如3":)会残留下来,形成"STORAGE_1"3":这类错误格式,同时长度变化会导致后续内容错位。 - VS安全机制限制:VS的文件操作函数对读写切换有严格要求,读写之间如果没有用
fseek或fflush同步指针,会触发未定义行为,直接引发报错。
推荐解决方法:临时文件中转(最稳妥)
直接修改原文件容易损坏数据,用临时文件中转是最安全的方案,处理完成后替换原文件即可:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #define MAX_LINE_LENGTH 1000 int main() { FILE* fp_src; FILE* fp_temp; char line[MAX_LINE_LENGTH]; char* pos; int num; const char* src_path = "C:/Users/13383/Desktop/storage.txt"; const char* temp_path = "C:/Users/13383/Desktop/storage_temp.txt"; // 打开原文件只读 if (fopen_s(&fp_src, src_path, "r") != 0) { printf("打开原文件失败:%d\n", errno); exit(1); } // 打开临时文件写入 if (fopen_s(&fp_temp, temp_path, "w") != 0) { printf("创建临时文件失败:%d\n", errno); fclose(fp_src); exit(1); } while (fgets(line, MAX_LINE_LENGTH, fp_src) != NULL) { pos = strstr(line, "STORAGE_"); if (pos != NULL) { // 提取STORAGE_后的数字 num = atoi(pos + strlen("STORAGE_")); num -= 7252; // 定位原数字后的引号,保证格式正确 char* quote_pos = strchr(pos + strlen("STORAGE_"), '"'); if (quote_pos != NULL) { sprintf_s(pos + strlen("STORAGE_"), quote_pos - (pos + strlen("STORAGE_")), "%d", num); } } // 将处理后的行写入临时文件 fputs(line, fp_temp); } // 关闭文件句柄 fclose(fp_src); fclose(fp_temp); // 替换原文件 if (remove(src_path) != 0) { printf("删除原文件失败:%d\n", errno); remove(temp_path); exit(1); } if (rename(temp_path, src_path) != 0) { printf("重命名临时文件失败:%d\n", errno); remove(temp_path); exit(1); } printf("处理完成!\n"); return 0; }
可选方案:原地修改原文件(不推荐)
如果能保证处理后的行长度和原行完全一致(比如原数字是4位,修改后也为4位),可以尝试原地修改,但风险较高:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE_LENGTH 1000 int main() { FILE* fp; char line[MAX_LINE_LENGTH]; char* pos; int num; long current_pos; if (fopen_s(&fp, "C:/Users/13383/Desktop/storage.txt", "r+") != 0) { printf("打开文件失败\n"); exit(1); } while ((current_pos = ftell(fp)) != -1 && fgets(line, MAX_LINE_LENGTH, fp) != NULL) { pos = strstr(line, "STORAGE_"); if (pos != NULL) { num = atoi(pos + strlen("STORAGE_")); num -= 7252; // 注意:必须保证修改后的数字长度和原数字一致,否则会损坏文件 sprintf_s(pos + strlen("STORAGE_"), MAX_LINE_LENGTH - (pos - line) - strlen("STORAGE_"), "%d\"", num); // 将指针移回当前行开头 fseek(fp, current_pos, SEEK_SET); // 写入处理后的行 fputs(line, fp); // 刷新缓冲区同步指针 fflush(fp); } } fclose(fp); printf("处理完成!\n"); return 0; }
额外提示
- 临时文件方案几乎不会出错,无论行长度如何变化都能正确处理,且中途出错时原文件不会损坏。
- 原地修改仅适用于行长度完全不变的场景,一旦长度变化会直接导致文件内容错位、损坏。
备注:内容来源于stack exchange,提问作者KabiLink
相关产品推荐
相关产品推荐

