2017-03-01 2 views
1

J'étudie le fichier binaire de C++ de nos jours. J'ai fait un exemple de code pour ça, mais ça ne marche pas bien.Valeur de poubelle lors de l'obtention d'une valeur entière à partir du fichier binaire en C++

#include <iostream> 
#include <fstream> 
using namespace std; 

int main() { 
    ofstream writeFile; 
    ifstream readFile; 
    int temp = 1; 

    writeFile.open("file.dat", ios::binary); 

    for (int i = 5; i <= 10 ; i++) // range 5 to 10 
     writeFile.write((char*)(&i), sizeof(i)); 

    writeFile.close(); 

    readFile.open("file.dat", ios::binary); 
    readFile.seekg(0); 
    while (!readFile.eof()) { 
     readFile.read((char*)(&temp), sizeof(temp)); 
     cout << "temp: " << temp << endl; 
     readFile >> ws; 
    } 
    readFile.close(); 

    system("pause"); 
    return 0; 
} 

Voici le résultat:

temp: 5 
temp: 6 
temp: 7 
temp: 8 
temp: 167772160 
temp: 167772160 

Quand je change la gamme de ne pas inclure 9 (par exemple, 5 à 8), il fonctionne bien. Aussi, quand je fais le même code avec le double type, ça marche bien. Donc, je pense que l'entier 9 est un problème. Peux-tu me dire pourquoi?

Répondre

4

readFile >> ws; supprime l'espace blanc, ce qui est un non-sens pour un flux binaire. Dans ce cas, la valeur de caractère 9 ('\t') est ignorée, ce qui corrode votre flux. Retirez simplement cette ligne.

Le deuxième problème est que vous ne vérifiez pas l'état du flux entre la lecture et l'affichage de la valeur. EOF est seulement détecté après une lecture dépasserait la fin du fichier. C'est pourquoi vous obtenez deux fois votre valeur invalide, la deuxième fois que la lecture échoue et laisse simplement temp avec sa valeur précédente. See this question pour plus de détails.

+0

La valeur 9 est en fait '\ t'. 10 est '\ n'. Le fait que les deux sont considérés comme des espaces blancs est ce qui provoque le problème. – IInspectable

+0

Ou plutôt, 'readFile >> ws' saute le caractère' \ t', puis la lecture des quatre octets '00 00 00 0a', interprétés comme un entier de 4 octets little-endian, est la valeur 167772160. C'est toujours bien défini (je crois). Cependant, la tentative de lecture suivante se lit au-delà de l'EOF. C'est UB, et l'affichage 167772160 est une forme valide de comportement indéfini. – IInspectable

1

The answer by François Andrieux a déjà la réponse à la question de savoir pourquoi votre code se comporte comme il le fait.

Voici quelques méthodes pour résoudre le problème.

  1. Utilisez une boucle for pour lire les nombres. Il reflète la boucle utilisée pour écrire dessus.

    readFile.open("file.dat", ios::binary); 
    for (int i = 5; i <= 10 ; i++) 
    { 
        readFile.read((char*)(&temp), sizeof(temp)); 
        cout << "temp: " << temp << endl; 
    } 
    readFile.close(); 
    
  2. Utilisez correctement la boucle while.

    readFile.open("file.dat", ios::binary); 
    while (readFile.read((char*)(&temp), sizeof(temp))) 
    { 
        cout << "temp: " << temp << endl; 
    } 
    readFile.close();