使用带文件的fseek(文件,0,SEEK_END)了解二进制流的未定义行为

问题描述 投票:12回答:1

C规范有一个有趣的脚注(#268C11dr§7.21.39)

“将文件位置指示符设置为文件结尾,与fseek(file, 0, SEEK_END)一样,对于二进制流具有未定义的行为(因为可能存在尾随空字符),或者具有状态相关编码的任何流在初始移位中无法确定结束州。”

这是否适用于读取文件的二进制流? (从物理设备)

IMO,磁盘上的二进制文件只是一个字节的海洋。在我看来,二进制文件不能具有状态相关的编码,因为它是一个二进制文件。我对“二进制广泛的流”的概念很模糊,如果它甚至可以应用于磁盘I / O.

我看到在串口流上调用fseek(file, 0, SEEK_END)就像一个com端口或者stdin可能无法达到真正的目的,因为结束尚未确定。从而将问题缩小到物理文件。


[编辑]答案:与老年人(可能直到20世纪80年代末)的关注。目前在2014年,Windows,POSIT特定和非异国他人:不是问题。

@Shafik Yaghmour在Using fseek and ftell to determine the size of a file has a vulnerability?提供了一个很好的参考。 @Jerry Coffin讨论CP/M作为二进制文件并不总是具有精确的长度。 (每个维基128字节的记录)。

感谢@Keith Thompson的回答。

这一点解释了规范的“(因为可能有尾随空字符)”评论。

c file-io binary fseek
1个回答
7
投票

在您可能使用的任何系统上,二进制文件将是具有精确指定大小的8位字节序列。但并非所有系统都以这种方式存储文件,而且C标准经过精心设计,可以移植到具有不寻常特性的系统。

例如,符合要求的C实现可以在操作系统上运行,该操作系统将文件存储为512字节块的序列,而不指示最终块的多少字节是重要的。在这样的系统上,当创建二进制文件时,OS可能用零字节填充最后一个块的剩余部分。从这样的文件读取时,填充字节可能出现在输入中(即使它们从未显式写入文件),也可能被忽略(即使创建该文件的程序可能已明确写入) 。

如果您正在从不可搜索的流中读取(例如键盘输入),那么fseek(file, 0, SEEK_END)将不会仅仅给您一个错误的结果,它将通过返回非零结果来指示失败。 (在符合POSIX的系统上,它返回-1并设置errno; ISO C不需要它。)

在大多数系统上,二进制文件上的fseek(file, 0, SEEK_END)将寻找文件的实际末尾(由确切地写入文件的字节数确定的位置),或返回明确的失败指示。如果你正在使用POSIX特定的功能,你可以安全地假设这种行为;您可以对Windows和许多其他系统做出相同的假设。如果您希望您的代码100%可移植到异国情调的系统,您不应该假设二进制文件不会被额外的零字节填充。

© www.soinside.com 2019 - 2024. All rights reserved.