fopen和freopen有什么区别?

4
"freopen"是否多余?
2个回答

7
根据POSIX(请参见应用使用部分),freopen最初是添加到C语言中的,以便将stdinstdout更改为二进制模式。我怀疑如果你深入研究ANSI / ISO理由文件,你可以找到对该声明的支持。正如POSIX文档所述,在POSIX系统上使用这种方式是没有意义的(其中文本和二进制模式需要表现出相同的行为),而严格遵循规范会导致文件被截断,从而具有实际上的有害性。
至于实际应用,以下是我能想到的一些:
  • 在执行外部程序之前,替换stdinstdoutstderr - 但我不确定POSIX是否要求freopen重用与原始FILE相同的文件描述符号,因此我不确定这是保证可行的。我总是简单地使用opendup2来实现此目的。
  • 一个接受调用者FILE *的日志记录库可能使用freopen将其置于追加模式,以确保所有数据都写入到末尾,即使另一个程序写入日志文件。
  • 如果您已经传递并存储了FILE *指针到程序中的许多组件,并且您发现后来需要支持交换文件(例如,考虑日志轮换),那么freopen比跟踪存储FILE *的每个位置并插入代码更新每个实例或包装FILE *在自己的结构中更容易。
所有这些的实用性都受到了freopen在失败时的不良行为的限制;FILE *变得无效且无法恢复,因此如果程序的任何部分仍可能在使用它,则必须找到一种方法来防止进一步访问或立即exit。同样,由于相同的原因,freopen不是线程安全的;如果它失败,从任何其他线程访问文件会导致未定义的行为。

1
“但我不确定POSIX是否要求freopen重用与原始FILE相同的文件描述符号码。” 在iOS上,我们观察到freopen有时会将另一个fd(而不是fd 2)分配给stderr。不能保证重用相同的fd。 - Chaitanya Gupta

6

不,freopen() 不是多余的。例如,它使您能够将文件打开为标准输入,否则您不能依赖实现。

如果您必须调用一个函数(您没有源代码,因此无法修复它),该函数读取特定文件流(通常是标准输入)或写入特定文件流(通常是标准输出),但是您不希望函数读取或写入与程序中连接的文件,则可以使用 freopen() 来修复问题,以便函数看到其期望的内容,但从您想要的地方获取信息 - 或者在您想要的位置写入它。


但是有必要更改无法通过处理用户流(printf->fprintf)替换的标准流吗? - Vovanium
@Vovanium:看看我的答案,虽然我认为它们的价值有待商榷。 - R.. GitHub STOP HELPING ICE
@Vovanium:如果你能指定流,因为被调用的代码使用fprintf()在你交给它的流上,而不是printf(),那么就没有理由使用freopen()。在25年以上的C编程中,我认为我只用过freopen()几次,如果有的话。正如@R..所指出的,如果你想做一些诸如将标准输出重置回其原始文件之类的事情,在重定向完成后,你会跳出C标准的范畴,进入POSIX领域并使用文件描述符。例如,fdopen()为文件描述符创建一个流;我经常使用它。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接