fread/ftell 在 Windows 下明显损坏,在 Linux 下工作正常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3187693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
fread/ftell apparently broken under Windows, works fine under Linux
提问by Ivo Wetzel
So here's the problem, I'm reading a level file for my game, works fine under linux:
所以问题来了,我正在为我的游戏读取关卡文件,在 linux 下运行良好:
@0
@12
200x200 version 3
@16
973 blocks
@989
@993
18 zones
But under windows I get the following result:
但在 Windows 下,我得到以下结果:
@0
@212
200x200 version 3
@216
973 blocks
@1200
@1204
18 zones
Uh? The windows ftell stats with an offset of 200? Reading the file apparently yields the same data, but fread uses(?) the value of ftell to determine the how many bytes are left in the file that can be read. So of course I'm running into problems when reading at the end of the file:
嗯?偏移量为 200 的 windows ftell 统计数据?读取文件显然会产生相同的数据,但 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.
This is the corresponding code(currently a bit ugly due to all the debug prints..):
这是相应的代码(由于所有调试打印,目前有点难看..):
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;
}
I really have no clue what's going on here. Compilers are the Visual Studio 10 one and GCC 4.4 under Linux.
我真的不知道这里发生了什么。编译器是 Linux 下的 Visual Studio 10 one 和 GCC 4.4。
回答by unwind
Open your file in binary mode:
以二进制模式打开文件:
FILE *fp = fopen(file_name, "rb");
In text mode, there might be translations going on to match the operating system-dependent encoding of e.g. line feeds to the C library's.
在文本模式下,可能会进行翻译以匹配操作系统相关的编码,例如换行到 C 库的编码。
回答by CB Bailey
ftell
and fseek
are only going to work as byte offsets if you open the file in binary mode, (i.e. "rb"
instead of "r"
). Otherwise you can only fseek
to things that have previously be returned by ftell
; the result of fseek
isn't going to be a byte offset.
ftell
并且fseek
仅当您以二进制模式打开文件时才用作字节偏移量(即,"rb"
而不是"r"
)。否则,您只能fseek
返回以前由ftell
;返回的东西;的结果fseek
不会是字节偏移量。
Binary mode makes a difference on windows where text mode maps the two character carriage return, line feed sequence to a single new-line character. No mapping is needed on linux.
二进制模式在 Windows 上有所不同,其中文本模式将两个字符回车、换行序列映射到单个换行符。在 linux 上不需要映射。
回答by Joakim
You should not be using ftell
and fseek
to determine the size of a file since it might be the source of vurnerabilities:
您不应该使用ftell
和fseek
来确定文件的大小,因为它可能是漏洞的来源: