fread / ftell显然在Windows下坏了,在Linux下工作正常

所以这里是这个问题,我正在阅读我的游戏关卡文件,在linux下工作正常:

@0 @12 200x200 version 3 @16 973 blocks @989 @993 18 zones 

但在Windows下,我得到以下结果:

 @0 @212 200x200 version 3 @216 973 blocks @1200 @1204 18 zones 

呃? 窗口ftell统计偏移量为200? 读取文件显然会产生相同的数据,但fread使用(?)ftell的值来确定文件中可以读取的字节数。 所以当然,我在阅读文件结尾时遇到了一些问题:

 @1425 zone#9 2x3 @ 66/9 @1425 zone#10 2x3 @ 66/9 @1425 zone#11 2x3 @ 66/9 @1425 zone#12 2x3 @ 66/9 @1425 zone#13 2x3 @ 66/9 @1425 zone#14 2x3 @ 66/9 etc. 

这是相应的代码(由于所有的debugging打印,目前有点丑陋):

 void fread_all(void *ptr, size_t size, size_t count, FILE *stream) { fread(ptr, size, count, stream); printf("@%ld\n", ftell(stream)); } bool map_load(struct Map *map, const char *file_name) { FILE *fp = fopen(file_name, "r"); if (fp != NULL) { fseek(fp, 0, SEEK_SET); printf("@%ld\n", ftell(fp)); // Header int *header = (int*)calloc(sizeof(int), 3); fread_all(header, sizeof(int), 3, fp); printf("%dx%d version %d\n", header[0], header[1], header[2]); map->pos_x = 0; map->pos_y = 0; map->map_x = 0; map->map_y = 0; map->size_x = header[0]; map->size_y = header[1]; map_zones_remove(map); free(header); // Blocks unsigned int *block_size = (unsigned int*)malloc(sizeof(unsigned int)); fread_all(block_size, sizeof(int), 1, fp); printf("%d blocks\n", *block_size); unsigned char *block_data = (unsigned char*)calloc(sizeof(unsigned char), *block_size); fread_all(block_data, sizeof(unsigned char), *block_size, fp); unsigned char *tmp = map->blocks; map->blocks = rle_decode(block_data, *block_size); free(tmp); free(block_size); free(block_data); // Zones int *zone_count = (int*)malloc(sizeof(int)); fread_all(zone_count, sizeof(int), 1, fp); printf("%d zones\n", *zone_count); int *d = (int*)calloc(sizeof(int), 6); for(int i = 0, l = *zone_count; i < l; i++) { fread_all(d, sizeof(int), 6, fp); map_zone_create(map, d[0], d[1], d[2], d[3], d[4], d[5]); printf("zone#%d %dx%d @ %d/%d\n", i, d[2], d[3], d[0], d[1]); } map_platforms_create(map); free(zone_count); free(d); fclose(fp); return true; } return false; } 

我真的不知道这里发生了什么事情。 编译器是Linux下的Visual Studio 10和GCC 4.4。

Solutions Collecting From Web of "fread / ftell显然在Windows下坏了,在Linux下工作正常"

以二进制模式打开文件:

 FILE *fp = fopen(file_name, "rb"); 

在文本模式下,可能会进行翻译以匹配例如换行符的操作系统相关编码到C库。

如果以二进制模式打开文件(即"rb"而不是"r" ), ftellfseek只能作为字节偏移量工作。 否则,你只能找到以前由ftell返回的东西; fseek的结果不会是一个字节偏移量。

二进制模式在文本模式将两个字符回车换行符映射到单个换行符的窗口上有所不同。 在linux上不需要映射。

您不应该使用ftellfseek来确定文件的大小,因为它可能是vurnerabilities的来源:

https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size + A +常规+文件+