La lecture d'un fichier volumineux à l'aide de C (de plus de 4 go) à l'aide de la fonction de lecture, à l'origine des problèmes
Je dois écrire le code en C pour la lecture 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);
}
La question, je suis confronté ici est que, tant que l'argument passé (paramètre de taille) est à moins de 264000000 octets, il semble être capable de le lire. Je reçois les tailles de plus en plus de la partie variable à chaque cycle.
Quand je passe la 264000000 octets ou plus, la lecture échoue, c'est à dire: d'après la vérification utilisée read renvoie -1.
Quelqu'un peut-il m'indiquer pourquoi ce qui se passe? Je suis à la compilation à l'aide de cc en mode normal, pas en utilisant DD64.
Quel système d'exploitation?
double possible pour stackoverflow.com/questions/3825896/...
Il ya de sérieux problèmes avec votre code que je peux voir. Tout d'abord, vous allouer un tampon de lire, à l'aide de
Quatrièmement, vous libérer de la mémoire tampon à l'intérieur de la boucle, mais ne pas allouer un nouveau. Cela signifie que la seconde itération, il va lire dans la mémoire non allouée. Cinquièmement, l'appel de
Et enfin, vous ne devrait pas vraiment être à l'aide de
double possible pour stackoverflow.com/questions/3825896/...
Il ya de sérieux problèmes avec votre code que je peux voir. Tout d'abord, vous allouer un tampon de lire, à l'aide de
size
que la taille. Ensuite vous lire info le tampon, en utilisant une taille fixe abstraction de la répartition de la taille de la mémoire tampon de vous lire. Pensez à ce qui va se passer si size
est moins de 250k. Deuxièmement, comme le fichier est de nouveau ouvert, vous n'avez pas besoin de chercher à le début. Troisièmement, vous chercher à size
, mais est size
le nombre d'enregistrements dans le fichier ou d'un nombre d'octets? Vous utilisez size
différemment lors de l'allocation de la mémoire tampon.Quatrièmement, vous libérer de la mémoire tampon à l'intérieur de la boucle, mais ne pas allouer un nouveau. Cela signifie que la seconde itération, il va lire dans la mémoire non allouée. Cinquièmement, l'appel de
read
va passer automatiquement de la position dans le fichier, vous n'avez pas besoin de chercher à chaque fois. Sixième, quand vous lisez, vous vérifier pour les erreurs, mais pas pour la fin-de-fichier. read
retourne 0
sur fin-de-fichier.Et enfin, vous ne devrait pas vraiment être à l'aide de
read
lors de la lecture d'un fichier de grande taille. En utilisant par exemple mmap
c'est sans doute une solution plus efficace, surtout si vous êtes de la lecture du fichier de manière séquentielle.OriginalL'auteur srijeet | 2012-08-03
Vous devez vous connecter pour publier un commentaire.
En premier lieu, pourquoi avez-vous besoin
lseek()
dans votre cycle?read()
va faire avancer le curseur dans le fichier par le nombre d'octets lus.Et, pour le sujet: long, et, respectivement, chunk, ont une valeur maximale de
2147483647
, un nombre plus grand que celui qui va réellement devenir négatif.Vous souhaitez utiliser
off_t
de déclarer morceau:off_t chunk
, de taille et desize_t
.C'est la raison principale pourquoi
lseek()
échoue.Et, de nouveau, comme d'autres personnes l'ont remarqué, vous ne voulez pas
free()
votre tampon à l'intérieur du cycle.Notez également que vous écrasera les données que vous avez déjà lu.
En outre,
read()
ne sera pas nécessairement lire autant que vous avez demandé, il est donc préférable d'avance morceau par la quantité d'octets réellement lus, plutôt que de la quantité d'octets que vous souhaitez lire.De prendre tout ce en ce qui concerne, le code correct doit probablement ressembler à quelque chose comme ceci:
J'ai aussi pris la liberté de supprimer variable résultat et de toute logique puisque, je crois, il peut être simplifié.
Edit: j'ai remarqué que certains systèmes (notamment, BSD) n'ont pas
O_LARGEFILE
, puisqu'il n'est pas nécessaire. Donc, j'ai ajouté un #ifdef au début, ce qui permettrait de rendre le code plus portable.OriginalL'auteur Senna
La fonction lseek peut avoir de la difficulté à soutenir de grandes tailles de fichier. Essayez d'utiliser lseek64
Veuillez vérifier le lien pour voir le associé macros qui doit être définie lorsque vous utilisez lseek64 fonction.
OriginalL'auteur Jay
Si son ordinateur 32 bits, cela va causer un problème pour la lecture d'un fichier de taille supérieure à 4 go. Donc, si vous utilisez le compilateur gcc essayez d'utiliser la macro
-D_LARGEFILE_SOURCE=1
et-D_FILE_OFFSET_BITS=64
.Veuillez cocher cette lien aussi
Si vous utilisez un autre compilateur de vérifier pour les mêmes types d'option de compilateur.
OriginalL'auteur rashok