2010-07-06 45 views
7
下正常工作

所以這裏的,我讀了我的遊戲級別文件的問題,在linux下正常工作:FREAD/FTELL Windows下顯然打破,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. 

這是相應的代碼(目前有點難看,由於所有的調試輸出..):

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。

回答

20

以二進制方式打開文件:

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

在文本模式下,有可能是翻譯正在進行匹配的例如操作系統相關的編碼提供給C庫的訂閱源。

+0

呃.....我的大腦必須採取嚴重損害最後幾天由於熱... -.-「它現在有效,謝謝! – 2010-07-06 15:34:52

4

ftellfseek只有在以二進制模式打開文件(即"rb"而不是"r")時才能用作字節偏移量。否則,您只能fseek以前由ftell返回的內容; fseek的結果不會是一個字節偏移量。

二進制模式在窗口中的區別在於文本模式將兩個字符回車,換行符序列映射到單個換行符。在linux上不需要映射。

+0

儘管我仍然覺得fread簡單地相信ftell的價值有點奇怪,但是還有一個問題,爲什麼它是否使用文件中的第一個字節(C8)作爲偏移量? – 2010-07-06 15:38:16

0

你不應該使用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+of+a+regular+file

+0

內容已移至https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek %28%29 +和+ ftell%28%29 + to + compute + + + +常規+文件的+大小+ – dnet 2015-03-31 13:29:53

+0

好吧我更改了網址 – Joakim 2015-04-01 08:35:12