Lecture d’un fichier volumineux en utilisant C (supérieur à 4 Go) en utilisant la fonction de lecture, ce qui pose des problèmes

Je dois écrire du code C pour lire des fichiers volumineux. Le code est ci-dessous:

int read_from_file_open(char *filename,long size) { long read1=0; int result=1; int fd; int check=0; long *buffer=(long*) malloc(size * sizeof(int)); fd = open(filename, O_RDONLY|O_LARGEFILE); if (fd == -1) { printf("\nFile Open Unsuccessful\n"); exit (0);; } long chunk=0; lseek(fd,0,SEEK_SET); printf("\nCurrent Position%d\n",lseek(fd,size,SEEK_SET)); while ( chunk < size ) { printf ("the size of chunk read is %d\n",chunk); if ( read(fd,buffer,1048576) == -1 ) { result=0; } if (result == 0) { printf("\nRead Unsuccessful\n"); close(fd); return(result); } chunk=chunk+1048576; lseek(fd,chunk,SEEK_SET); free(buffer); } printf("\nRead Successful\n"); close(fd); return(result); } 

Le problème auquel je suis confronté ici est que tant que l’argument passé (paramètre de taille) est inférieur à 264000000 octets, il semble pouvoir lire. Je reçois les tailles croissantes de la variable chunk à chaque cycle.

Lorsque je passe 264000000 octets ou plus, la lecture échoue, c.-à-d.

Quelqu’un peut-il m’indiquer pourquoi cela se produit? Je comstack en utilisant cc en mode normal, sans utiliser DD64.

En premier lieu, pourquoi avez-vous besoin de lseek() dans votre cycle? read() fera avancer le curseur dans le fichier du nombre d’octets lus.

Et, sur le sujet: long, et, respectivement, chunk, ont une valeur maximale de 2147483647 , tout nombre supérieur à celui-ci deviendra réellement négatif.

Vous voulez utiliser off_t pour déclarer un morceau: off_t chunk et size_t . C’est la principale raison pour laquelle lseek() échoue.

Et, encore une fois, comme d’autres personnes l’ont remarqué, vous ne voulez pas free() votre tampon dans le cycle.

Notez également que vous allez écraser les données que vous avez déjà lues. En outre, read() ne lira pas nécessairement autant que vous l’avez demandé, il est donc préférable d’avancer le bloc en fonction de la quantité d’octets réellement lus, plutôt que de la quantité d’octets à lire.

En prenant tout en considération, le code correct devrait probablement ressembler à ceci:

 // Edited: note comments after the code #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif int read_from_file_open(char *filename,size_t size) { int fd; long *buffer=(long*) malloc(size * sizeof(long)); fd = open(filename, O_RDONLY|O_LARGEFILE); if (fd == -1) { printf("\nFile Open Unsuccessful\n"); exit (0);; } off_t chunk=0; lseek(fd,0,SEEK_SET); printf("\nCurrent Position%d\n",lseek(fd,size,SEEK_SET)); while ( chunk < size ) { printf ("the size of chunk read is %d\n",chunk); size_t readnow; readnow=read(fd,((char *)buffer)+chunk,1048576); if (readnow < 0 ) { printf("\nRead Unsuccessful\n"); free (buffer); close (fd); return 0; } chunk=chunk+readnow; } printf("\nRead Successful\n"); free(buffer); close(fd); return 1; } 

J'ai également pris la liberté de supprimer les variables de résultat et toute la logique associée, car, je crois, cela peut être simplifié.

Edit: J'ai noté que certains systèmes (notamment BSD) n'ont pas O_LARGEFILE , car il n'y est pas nécessaire. J'ai donc ajouté un #ifdef au début, ce qui rendrait le code plus portable.

La fonction lseek peut avoir des difficultés à prendre en charge des tailles de fichiers volumineuses. Essayez d’utiliser lseek64

Veuillez vérifier le lien pour voir les macros associées qui doivent être définies lorsque vous utilisez la fonction lseek64.

Si sa machine 32 bits, cela entraînera un problème pour la lecture d’un fichier de plus de 4 Go. Donc, si vous utilisez le compilateur gcc, essayez d’utiliser la macro -D_LARGEFILE_SOURCE=1 et -D_FILE_OFFSET_BITS=64 .

S’il vous plaît vérifier ce lien aussi

Si vous utilisez un autre compilateur, vérifiez les types similaires d’option du compilateur.