fseek - 无法跳过大量字节?
fseek - fails skipping a large amount of bytes?
我试图在使用 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);
fseek
的 offset
参数必须是 long
,而不是 long long
。所以 x
必须适合 long
,否则不要使用 fseek
。
fseek 的输入指南:
http://www.tutorialspoint.com/c_standard_library/c_function_fseek.htm
int fseek(FILE *stream, long int offset, int whence)
offset − This is the number of bytes to offset from whence.
您通过将 long long
(其值大于 Long int
的最大值)传递给 fseek 而不是所需的 long
.
来调用未定义的行为
众所周知,UB可以做任何事情,包括不工作。
由于您的平台的 int
很可能是 32 位的,将 649,218,227 乘以 sizeof(int)
得到的数字超过了 INT_MAX
和 LONG_MAX
,它们都是 2 **32 位平台上的 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);
假设 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;
}
试试这个,这么大的数字你可能要读出来
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;
}
我试图在使用 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);
fseek
的 offset
参数必须是 long
,而不是 long long
。所以 x
必须适合 long
,否则不要使用 fseek
。
fseek 的输入指南:
http://www.tutorialspoint.com/c_standard_library/c_function_fseek.htm
int fseek(FILE *stream, long int offset, int whence)
offset − This is the number of bytes to offset from whence.
您通过将 long long
(其值大于 Long int
的最大值)传递给 fseek 而不是所需的 long
.
众所周知,UB可以做任何事情,包括不工作。
由于您的平台的 int
很可能是 32 位的,将 649,218,227 乘以 sizeof(int)
得到的数字超过了 INT_MAX
和 LONG_MAX
,它们都是 2 **32 位平台上的 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);
假设 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;
}
试试这个,这么大的数字你可能要读出来
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;
}