和函数均由 ISO C 语言标准定义fseek
。ftell
以下是2011 C 标准的最新公开草案,但 1990、1999 和 2011 ISO C 标准在这方面都非常相似,如果不完全相同的话。
7.21.9.4:
ftell函数获取 stream 指向的流的文件位置指示符的当前值。对于二进制流,该值是从文件开头开始的字符数。对于文本流,其文件位置指示符包含未指定的信息,fseek函数可使用该信息将流的文件位置指示符返回到
ftell调用时的位置;两个这样的返回值之间的差异不一定是衡量写入或读取字符数的有意义的量度。
7.21.9.2:
fseek函数为 stream 指向的流设置文件位置指示符。如果发生读取或写入错误,则设置流的错误指示符并且fseek失败。
对于二进制流,新位置(以文件开头的字符为单位)是通过将offset添加到whence指定的位置来获得的。如果wherece是SEEK_SET ,则指定位置是文件的开头,如果是 SEEK_CUR,则为文件位置指示符的当前值,如果是SEEK_END ,则为文件结尾
。二进制流不需要有意义地支持wherece值为SEEK_END的fseek调用。
对于文本流,偏移量应为零,或偏移量
应为先前成功调用
与同一文件关联的流上的ftell函数返回的值,并且应为SEEK_SET。
违反任何“shall”子句会使您的程序的行为未定义。
因此,如果文件以二进制模式打开,则为ftell
您提供从文件开头开始的字符数——但fseek
相对于文件结尾 ( SEEK_END
) 不一定有意义。这适用于将二进制文件存储在整个块中并且不跟踪写入最终块的数量的系统。
如果文件以文本模式打开,您可以使用偏移量 0 查找文件的开头或结尾,或者您可以查找之前调用ftell
;给出的位置。fseek
与任何其他参数有未定义的行为。这适用于从文本文件中读取的字符数不一定与文件中的字节数相对应的系统。例如,在 Windows 上读取 CR-LF 对 ( "\r\n"
) 只会读取一个字符,但会在文件中前进 2 个字节。
实际上,在类 Unix 系统上,文本和二进制模式的行为方式相同,并且 fseek/ftell 方法将起作用。我怀疑它可以在 Windows 上运行(我的猜测是它ftell
会给出字节偏移量,这可能与您getchar()
在文本模式下调用的次数不同)。
另请注意,ftell()
返回类型的结果long
。在long
32 位系统上,此方法不适用于 2 GiB 或更大的文件。
您最好使用一些特定于系统的方法来获取文件的大小。因为 fseek/ftell 方法无论如何都是系统特定的,例如stat()
在类 Unix 系统上。
另一方面,fseek
并且可能在您可能遇到的大多数ftell
系统上按预期工作。我敢肯定有些系统不起作用。对不起,但我没有具体细节。
如果在 Linux 和 Windows 上工作足够好,并且您不关心大文件,那么 fseek/ftell 方法可能没问题。否则,您应该考虑使用特定于系统的方法来确定文件的大小。
请记住,任何告诉您文件大小的东西都只能告诉您当时的大小。在您访问它之前,文件的大小可能会发生变化。