32 bits de Windows et le fichier de 2 go de limite de taille (C avec fseek et ftell)
Je tente de port une petite analyse des données du programme à partir d'un UNIX 64 bits à 32 bits de Windows XP (ne demandez pas :)).
Mais maintenant, je vais avoir des problèmes avec les 2 go de limite de taille de fichier (longue de ne pas être en 64 bits sur cette plate-forme).
J'ai cherché sur ce site et les autres pour possible sollutions, mais ne trouvez pas tout qui sont directement traduisible à mon problème.
Le problème est dans l'utilisation de fseek et ftell.
Personne ne sait d'une modification à l'une des deux fonctions suivantes pour les faire travailler sur la 32 bits de Windows XP pour les fichiers supérieurs à 2 GO (en fait de l'ordre de 100 go).
Il est essentiel que le type de retour de nsamples est un entier de 64 bits (éventuellement int64_t).
long nsamples(char* filename)
{
FILE *fp;
long n;
/* Open file */
fp = fopen(filename, "rb");
/* Find end of file */
fseek(fp, 0L, SEEK_END);
/* Get number of samples */
n = ftell(fp) / sizeof(short);
/* Close file */
fclose(fp);
/* Return number of samples in file */
return n;
}
et
void readdata(char* filename, short* data, long start, int n)
{
FILE *fp;
/* Open file */
fp = fopen(filename, "rb");
/* Skip to correct position */
fseek(fp, start * sizeof(short), SEEK_SET);
/* Read data */
fread(data, sizeof(short), n, fp);
/* Close file */
fclose(fp);
}
J'ai essayé d'utiliser _fseeki64 et _ftelli64 à l'aide de la suivante pour remplacer nsamples:
__int64 nsamples(char* filename)
{
FILE *fp;
__int64 n;
int result;
/* Open file */
fp = fopen(filename, "rb");
if (fp == NULL)
{
perror("Error: could not open file!\n");
return -1;
}
/* Find end of file */
result = _fseeki64(fp, (__int64)0, SEEK_END);
if (result)
{
perror("Error: fseek failed!\n");
return result;
}
/* Get number of samples */
n = _ftelli64(fp) / sizeof(short);
printf("%I64d\n", n);
/* Close file */
fclose(fp);
/* Return number of samples in file */
return n;
}
pour un fichier de 4815060992 octets - je obtenir 260046848 des échantillons (p. ex. _ftelli64
donne 520093696 octets) qui est étrange.
Curieusement lorsque je quitte le (__int64)
exprimés dans l'appel à _fseeki64
j'obtiens une erreur à l'exécution (argument non valide).
Des idées?
Quel compilateur que vous utilisez? gcc? Visuel (quelque chose)? Quelque chose d'autre?
J'utilise MinGW ("ne peut pas" utiliser VS depuis les fonctions, je suis en train d'écrire font partie d'un f2py Python module d'extension). L'API Win32 pourrait être une option si elle pouvait être facilement intégré dans cette fonction sans ajouter de nombreuses dépendances (comme vous pouvez probablement dire que je ne suis pas familier avec Windows :))
J'ai posté une question plus spécifique, si répondu, je vais ajouter la solution finale.
OriginalL'auteur Pim Schellart | 2010-10-23
Vous devez vous connecter pour publier un commentaire.
Il y a deux fonctions appelées _fseeki64 et _ftelli64 qui prennent en charge plus de décalages de fichier, même sur 32 bits de Windows:
Quel compilateur utilisez-vous? VisualStudio? Et quelle version?
J'utilise la dernière version de MinGW (essentiellement GCC 4.5). Comme le paquet que je suis la compilation est une extension Python avec f2py et je n'ai aucune idée de comment compiler qu'avec VisualStudio.
Je n'ai jamais utilisé de MinGW je crains que je ne peux pas vraiment l'aider. Mais avez-vous regardé ftello et fseeko, qui sont les versions 64 bits de ftell et fseek disponible sous Unix comme les bibliothèques?
J'ai regardé comme ces (fseeko _ftello) fonctions mais ne suis pas sûr s'ils travaillent également sur Windows (sur mon 64 bits machine UNIX il n'y a pas de problème puisque je peux utiliser fseek et ftell avec le 64 bits de long, c'est vraiment un Windows question spécifique).
OriginalL'auteur Codo
désolé de ne pas poster plus tôt, mais j'ai été préoccupé par d'autres projets, pour un certain temps.
La solution suivante fonctionne:
Le truc a l'aide de
_open
au lieu defopen
pour ouvrir le fichier.Je ne comprends toujours pas exactement pourquoi cela doit être fait, mais au moins cela fonctionne maintenant.
Merci à tous pour vos suggestions qui finalement m'a orienté dans la bonne direction.
OriginalL'auteur Pim Schellart
Mon BC dit:
Je devine que votre routine d'impression est de 32 bits. Votre décalage retourné est probablement correct mais le fait d'être coupé quelque part.
OriginalL'auteur dascandy
Et pour gcc, voir DONC, la question Million trente cinq mille six cent cinquante sept. Lorsque le conseil est de compiler avec l'option -D_FILE_OFFSET_BITS=64 donc que la variable cachée(s) (de type off_t) utilisé par le f-se déplacer-autour des fonctions est(sont) 64-bits.
Pour MinGW: "Grand-prise en charge des fichiers (EPA) a été mis en œuvre par la redéfinition de la statistique et de chercher des fonctions et des types de 64 bits équivalents. Pour fseek et ftell, distinct de l'EPA versions, fseeko et ftello, basé sur fsetpos et fgetpos, sont fournis dans LibGw32C." (référence). Dans les versions récentes de gcc, fseeko et ftello sont intégrés et une bibliothèque séparée n'est pas nécessaire.
Schellart: je ne peux ni confirmer ni nier que. Mes deux actuellement en train de travailler gcc configurations Linux/POSIX (dans le contexte de votre question). Essai sur ceux, je vois EFT comportement de fseek() et ftell(). Donc, je ne suis pas en mesure de tester avec gcc dans un non-POSIX environnement.
fseeko et ftello sont fournis avec la dernière MinGW gcc 4.8.2; vous n'avez pas besoin LibGw32C.
OriginalL'auteur Eric Towers