2010-07-06 5 views
7

Voici donc le problème, je lis un fichier de niveau pour mon jeu, fonctionne très bien sous linux:fread/ftell apparemment cassé sous Windows, fonctionne très bien sous Linux

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

Mais sous Windows, je reçois le texte suivant résultat:

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

Uh? Les statistiques Windows ftell avec un décalage de 200? La lecture du fichier donne apparemment les mêmes données, mais fread utilise (?) La valeur de ftell pour déterminer le nombre d'octets restant dans le fichier qui peut être lu. Alors bien sûr, je suis en cours d'exécution dans des problèmes lors de la lecture à la fin du fichier:

@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. 

Voici le code correspondant (actuellement un peu laid en raison de toutes les impressions de débogage ..):

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; 
} 

Je n'ai vraiment aucune idée de ce qui se passe ici. Les compilateurs sont Visual Studio 10 et GCC 4.4 sous Linux.

Répondre

20

Ouvrez votre fichier en mode binaire:

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

En mode texte, il pourrait y avoir des traductions en cours pour correspondre à l'encodage dépendant du système d'exploitation par exemple sauts de ligne vers la bibliothèque C.

+0

Euh ..... mon cerveau doit avoir pris au sérieux dégâts dans les derniers jours à cause de la chaleur ... -.- "Ça marche maintenant, merci! –

4

ftell et fseek vont seulement travailler comme des décalages d'octets si vous ouvrez le fichier en mode binaire, (à savoir "rb" au lieu de "r"). Sinon, vous pouvez seulement fseek à des choses qui ont déjà été retournées par ftell; le résultat de fseek ne va pas être un décalage d'octet.

Le mode binaire fait la différence sur les fenêtres dans lesquelles le mode texte associe la séquence de retour chariot et de saut de ligne à un seul caractère de nouvelle ligne. Aucune cartographie n'est nécessaire sur Linux.

+0

Cela a fait l'affaire, même si je trouve encore un peu étrange que Fread se fie simplement à la valeur de ftell. utilise-t-il le premier octet (C8) du fichier en tant que décalage? –

0

Vous ne devriez pas utiliser ftell et fseek pour déterminer la taille d'un fichier, car il pourrait être la source de 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

Le contenu a été déplacé vers https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek % 28% 29 + et + ftell% 28% 29 + à + calculer + la + taille + de + un + régulier + fichier – dnet

+0

Ok, j'ai changé l'URL – Joakim

Questions connexes