C规范有一个有趣的脚注(#268C11dr§7.21.39)
“将文件位置指示符设置为文件结尾,与
fseek(file, 0, SEEK_END)
一样,具有二进制流的未定义行为(因为可能是尾随空字符)或具有状态相关编码的任何流不能确定地在最初的轮班状态结束。“
这是否适用于读取文件的二进制流?(来自物理设备)
IMO,磁盘上的二进制文件只是一个字节的海洋。在我看来,二进制文件不能具有状态相关的编码,因为它是二进制文件。我对“二进制广泛流”的概念很模糊,如果它甚至可以应用于磁盘I / O.
我发现在串口流上调用fseek(file, 0, SEEK_END)
(如com端口或stdin
)可能无法到达真正的结尾,因为 end 尚未确定。从而将问题缩小到物理文件。
[编辑]答案:关注年龄较大(可能直到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的回答。
这一起解释了规范的“(因为可能有尾随空字符)”评论。
答案 0 :(得分:7)
在您可能使用的任何系统上,二进制文件将是具有精确指定大小的8位字节序列。但所有系统都没有这样存储文件,C标准经过精心设计,可以移植到具有不寻常特性的系统。
例如,符合标准的C实现可能在操作系统上运行,该操作系统将文件存储为512字节块的序列,而不指示最终块的多少字节是重要的。在这样的系统上,当创建二进制文件时,OS可能用零字节填充最后一个块的剩余部分。从这样的文件读取时,填充字节可能出现在输入中(即使它们从未显式写入文件),也可能被忽略(即使创建该文件的程序可能已明确写入)
如果您正在从不可搜索的流中读取(例如键盘输入),那么fseek(file, 0, SEEK_END)
将不会仅仅给您一个错误的结果,它将通过返回非零结果来指示失败。 (在符合POSIX的系统上,它返回-1并设置errno
; ISO C不要求它。)
在大多数系统上,二进制文件上的fseek(file, 0, SEEK_END)
将寻找文件的实际末尾(由确切地写入文件的字节数确定的位置),或返回明确的失败指示。如果你正在使用POSIX特定的功能,你可以安全地假设这种行为;您可以对Windows和许多其他系统做出相同的假设。如果您希望您的代码100%可移植到异国情调的系统,您不应该假设二进制文件不会被额外的零字节填充。