fseek - 无法跳过大量字节?

时间:2016-01-11 09:36:24

标签: c fseek

在尝试使用fread读取下一个字节之前,我试图跳过大量字节。 当尺寸很小#define size 6404168时 - 它有效:

long int x = ((long int)size)*sizeof(int);
fseek(fincache, x, SEEK_CUR);

当大小很大#define size 649218227时,它不会:(下一个fread读取垃圾,无法真正理解它所读取的偏移量。

使用fread作为解决方法在两种情况下均有效,但速度很慢:

temp = (int *) calloc(size, sizeof(int));
fread(temp,1, size*sizeof(int), fincache);
free(temp);

5 个答案:

答案 0 :(得分:2)

假设sizoef(int)4并且您使用的是32位系统(sizeof(long)为4),

所以649218227 * 4会溢出 long 所能容纳的内容。有符号整数溢出是未定义的行为。因此,它适用于较小的值(小于LONG_MAX)。

您可以使用循环代替fseek()必需的字节。

long x;
intmax_t len = size;

for(;len>0;){    
   x = (long) (len>LONG_MAX?LONG_MAX:len);
   fseek(fincache, x, SEEK_CUR);
   len = len-x;
}

答案 1 :(得分:1)

offset的{​​{1}}参数必须是fseek,而不是long。因此long long必须符合x,否则请勿使用long

答案 2 :(得分:1)

fseek的输入指南:

http://www.tutorialspoint.com/c_standard_library/c_function_fseek.htm

int fseek(FILE *stream, long int offset, int whence)
  

offset - 这是从哪里偏移的字节数。

您通过将long long(其值大于Long int的最大值)传递给fseek而不是所需的long来调用未定义的行为。

众所周知,UB可以做任何事情,包括不工作。

答案 3 :(得分:1)

由于您的平台int最有可能是32位,因此将649,218,227与sizeof(int)相乘会产生超过INT_MAXLONG_MAX的数字,这是在32位平台上都是2 ** 31-1。由于fseek接受long int,因此产生的溢出会导致程序打印垃圾。

您应该查阅编译器的文档,以确定它是否为64位搜索提供了扩展。例如,在POSIX系统上,您可以使用fseeko,它接受​​off_t类型的偏移量。

在调用64位搜索功能之前,请注意不要引入溢出。细致的代码可能如下所示:

off_t offset = (off_t) size * (off_t) sizeof(int);
fseeko(fincache, offset, SEEK_CUR);

答案 4 :(得分:0)

试试这个,如果数量如此之大,你可能需要阅读它

 size_t toseek = 6404168;
 //change the number to increase it
 while(toseek>0)
 {
    char buffer[4096];
    size_t toread = min(sizeof(buffer), toseek);
    size_t read = fread(buffer, 1, toread, stdin);
    toseek = toseek - read;
 }
相关问题