C语言使用freopen返回的FILE指针调用fgets读取重定向文件失效问题
问题原因分析
1. 为什么freopen返回的pointer无法正常读取
核心原因有两点:
pointer对应的流已经被第二次freopen调用隐式关闭
C标准对freopen的行为定义明确:当调用freopen(filename, mode, stream)将已有流stream关联到新文件时,会首先尝试关闭stream之前关联的所有资源,忽略关闭阶段的错误,再完成新的关联绑定。
你的代码中第一次freopen返回的pointer本质就是stdout本身(freopen调用成功时返回值等于传入的第三个流参数),后续调用freopen("/dev/tty", "w", stdout)重定向stdout到终端时,会自动关闭stdout之前关联的./check_str_out文件,此时pointer指向的流已经是无效的关闭状态,自然无法用于读取。- 即使流未关闭,直接读取也会返回EOF
你第一次打开文件用的是w模式,即使改成w+可读写模式,调用printer()写完所有内容后,文件的读写偏移量已经处于文件末尾,直接调用fgets读取会直接读到EOF,也不会进入循环,需要先调用rewind(pointer)把偏移量重置到文件开头才能正常读取内容。
2. 为什么freopen打开的流未调用fclose却看似被关闭
就是上面提到的freopen的隐式关闭逻辑:你第二次调用freopen重定向stdout的时候,已经自动完成了旧关联文件的关闭操作,不需要显式调用fclose,所以会出现没有主动调用fclose但流已经被关闭的现象。
若要直接用pointer读取的修正方案
如果你不想重新fopen文件,可以按以下步骤修改:
void check_string() { // 改成w+可读写模式 FILE* pointer = freopen("./check_str_out", "w+", stdout); char* storage = malloc(MAX_SEQ); char* test_results[] = {"00 00 01 02 03 04 05 \n", "10 00 01 02 03 04 05 \n", "20 00 01 02 03 04 05 \n", "30 00 01 02 03 04 05 \n", "40 00 01 02 03 04 05 \n", "\n"}; int counter = 0; printer(); fflush(stdout); // 确保所有写入内容都刷入文件 rewind(pointer); // 把文件偏移量重置到开头 printf("sth\n"); while (fgets(storage, MAX_SEQ, pointer)) { printf("sth2\n"); printf("count: %d, stor: %s, test: %s, comp: %d\n", counter, storage, test_results[counter], strcmp(storage, test_results[counter])); counter++; } // 读取完成后再重定向stdout回终端 freopen("/dev/tty", "w", stdout); free(storage); fclose(pointer); }
内容的提问来源于stack exchange,提问作者Funny
相关产品推荐
相关产品推荐

