FSEEK偏移接受超过它应接受的范围

时间:2017-05-09 12:27:08

标签: c fseek

关注Specification:

  

对于文本流,偏移量应为零,或者offset应为先前成功调用与同一文件关联的流上的ftell函数返回的值,并且应为SEEK_SET。

我了解offset必须是ftell函数的重新调整值,或0,而whence必须是SEET_SET(或0)。但我使用了一些整数作为偏移和不同的SEEK_...,它似乎运作良好。

例如,这些工作:

fseek(file, 4, SEEK_CUR);
fseek(file, -1, SEEK_END);
fseek(file, 0, SEEK_CUR);

当我阅读规范时,在我看来它应该不起作用。我试过这种方式多次使用fseek,它从未失败过。为什么它有效,我没有得到什么?

5 个答案:

答案 0 :(得分:2)

在ftell文档中,您可以阅读

  

对于文本流,数值可能没有意义但可以   仍然用于以后使用将位置恢复到相同位置   fseek(如果有使用ungetc的字符仍在等待中   正在阅读,行为未定义。)

你引用的意思是如果你知道你想把指针放在哪里就可以使用它,你可能知道它,因为在优先级你调用了ftell()。

你对fseek的所有调用都是有效的,但在文本文件中使用fseek进行移动没有太大意义,因为它不是随机访问(二进制)文件,但这并不意味着使用它是错误的它

对于文本文件,您可以找到here访问它的最常用函数,如fscanf(),fprintf()等。

答案 1 :(得分:1)

  

当我阅读规范时,在我看来它应该不起作用。

规范,陈述必须起作用的内容。它应该被视为创建c库的人的最低要求(即fseek等人的实现者)。

使用不当可能仍然有效,但无法保证。结果将取决于平台。

例如,fseek的Linux手册页说:

  

fseek()函数设置stream指向的流的文件位置指示符。以字节为单位测量的新位置是通过将偏移字节添加到由whence指定的位置来获得的。如果whence设置为SEEK_SET,SEEK_CUR或SEEK_END,则偏移量分别相对于文件的开头,当前位置指示符或文件结尾。成功调用fseek()函数会清除流的文件结束指示符,并撤消ungetc(3)函数对同一流的任何影响。

你可以看到,你尝试的东西在Linux中可用于文本和二进制流。但是,可能存在fseek无法与SEEK_CUR或SEEK_END一起使用文字流的平台。

另请注意,流可以与不同的东西相关联:文件,键盘,套接字,终端窗口,设备等。

答案 2 :(得分:0)

您的所有fseek来电均有效。您提供的第二个参数是偏移量,这意味着它与您提供的第三个参数的搜索类型相关。

fseek(file, 4, SEEK_CUR);    // seek 4 bytes forward from current position
fseek(file, -1, SEEK_END);   // seek to 1 byte before the end of the file
fseek(file, 0, SEEK_CUR);    // does nothing.

但另请参阅用户Tu.ma的解释,如果文件已在文本模式下打开(特别是在Windows下由于回车/换行翻译),搜索位置不准确和/或无意义。

答案 3 :(得分:0)

没有什么能阻止你使用fseek超越文件的当前大小。因为这样做可以让你在那时写入数据,填补与NUL之间尚未写入的差距。与此示例代码一样 - 它创建一个包含1000个NUL,然后是"hello\n"

的文件
#include <stdio.h>

int main(void)
    {
    FILE *f;

    f=fopen("test","w"); 
    if(f)
        {
        fseek(f,1000,SEEK_SET);
        fprintf(f,"hello\n");
        fclose(f);
        }
    else
        {
        perror("fopen");
        }
    }

答案 4 :(得分:0)

我认为fseek的定义与C标准中的主要原因是文本文件中的逻辑位置可能与文本文件开头的物理字节数无关。

例如,在Windows实现中,将磁盘上的\r\n转换为\n以保持与Unix行结尾的兼容性并不罕见。因此,如果您的文件如下所示:

hello\r\nworld

即。两行,而您fseek到第6位,您希望是\n还是w?如果您试图通过在Windows上使用fgetc来查找字符数,那么您可能会认为您将在w上。但是fseek可能会在不扫描行结尾的情况下前进到字节6。

修改

  

如果我们使用fgetc函数,我们读取的每个字符都会增加1的位置:文件光标在读取前一个字符后转到下一个字符。这是一个问题吗?

是。问题在于“性格”的定义。如果您所在的环境使用DOS约定,则当接下来的两个字节为fgetc时,在文本流上使用0x0d 0x0a将文件位置提前2,但仅返回0x0a。实现可能会进行其他转换,例如将分解的Unicode转换为预组合的unicode,反之亦然。

C标准中的措辞允许实现丢失文件中字节与fgetc返回的字符之间的一对一映射,而不必过度复杂fseek