fonction tellg () donne une taille de fichier incorrecte?

J’ai fait un exemple de projet pour lire un fichier dans un tampon. Lorsque j’utilise la fonction tellg (), cela me donne une valeur plus grande que la fonction de lecture lue dans le fichier. Je pense qu’il y a un bug.

voici mon code:

MODIFIER:

void read_file (const char* name, int *size , char*& buffer) { ifstream file; file.open(name,ios::in|ios::binary); *size = 0; if (file.is_open()) { // get length of file file.seekg(0,std::ios_base::end); int length = *size = file.tellg(); file.seekg(0,std::ios_base::beg); // allocate buffer in size of file buffer = new char[length]; // read file.read(buffer,length); cout << file.gcount() << endl; } file.close(); } 

principale:

 void main() { int size = 0; char* buffer = NULL; read_file("File.txt",&size,buffer); for (int i = 0; i < size; i++) cout << buffer[i]; cout << endl; } 

tellg ne rapporte pas la taille du fichier, ni le décalage depuis le début en octets. Il indique une valeur de jeton qui peut ensuite être utilisée pour rechercher le même endroit, et rien de plus. (Il n’est même pas garanti que vous puissiez convertir le type en un type intégral.)

Du moins en fonction de la spécification du langage: en pratique, sur les systèmes Unix, la valeur renvoyée sera le décalage en octets à partir du début du fichier et, sous Windows, ce sera le décalage à partir du début du fichier pour les fichiers ouverts dans. mode binary . Pour Windows (et la plupart des systèmes non-Unix), en mode texte, il n’y a pas de correspondance directe et immédiate entre les informations tellg et le nombre d’octets à lire pour accéder à cette position. Sous Windows, tout ce sur quoi vous pouvez vraiment compter est que la valeur ne sera pas inférieure au nombre d’octets que vous devez lire (et dans la plupart des cas, ce ne sera pas beaucoup plus grand, bien que cela puisse être jusqu’à deux fois plus ).

S’il est important de savoir exactement combien d’octets vous pouvez lire, le seul moyen fiable de le faire est de le lire. Vous devriez pouvoir faire ceci avec quelque chose comme:

 file.ignore( std::numeric_limits::max() ); std::streamsize length = file.gcount(); file.clear(); // Since ignore will have set eof. file.seekg( 0, std::ios_base::beg ); 

Enfin, deux autres remarques concernant votre code:

Tout d’abord, la ligne:

 *buffer = new char[length]; 

ne devrait pas comstackr: vous avez déclaré le buffer comme étant un caractère char* , donc *buffer a le type char et n’est pas un pointeur. Compte tenu de ce que vous semblez faire, vous voudrez probablement déclarer le buffer comme un caractère char** . Mais une solution bien meilleure serait de le déclarer comme un std::vector& ou un std::ssortingng& . (De cette façon, vous n’avez pas à renvoyer la taille également et vous ne perdrez pas de mémoire en cas d’exception.)

Deuxièmement, la condition de boucle à la fin est fausse. Si vous voulez vraiment lire un caractère à la fois,

 while ( file.get( buffer[i] ) ) { ++ i; } 

devrait faire l’affaire. Une meilleure solution serait probablement de lire des blocs de données:

 while ( file.read( buffer + i, N ) || file.gcount() != 0 ) { i += file.gcount(); } 

ou même:

 file.read( buffer, size ); size = file.gcount(); 

EDIT: Je viens de remarquer une troisième erreur: si vous ne parvenez pas à ouvrir le fichier, vous ne le dites pas à l’appelant. Au minimum, définissez la size sur 0 (mais une gestion plus précise des erreurs est probablement préférable).

 fseek(fptr, 0L, SEEK_END); filesz = ftell(fptr); 

fera le fichier si le fichier est ouvert via fopen

en utilisant ifstream,

 in.seekg(0,ifstream::end); dilesz = in.tellg(); 

ferait pareil

 void read_file (int *size, char* name,char* buffer) *buffer = new char[length]; 

Ces lignes ressemblent à un bogue: vous créez un tableau de caractères et enregistrez dans un caractère tampon [0]. Ensuite, vous lisez un fichier dans la mémoire tampon, qui n’est toujours pas initialisée.

Vous devez passer le buffer par pointeur:

 void read_file (int *size, char* name,char** buffer) *buffer = new char[length]; 

Ou par référence, qui est la manière c ++ et est moins sujette aux erreurs:

 void read_file (int *size, char* name,char*& buffer) buffer = new char[length]; ...