2014-01-03 3 views
4

Я пытаюсь написать двоичный файл, вот мой фрагмент кодаотладки строки чтения/записи в двоичный файл

#include <iostream> 
#include <fstream> 
#include <string> 

using namespace std; 

struct user 
{ 
    string ID; 
    string password;  
}; 

int main() 
{ 
    fstream afile; 
    afile.open("user.dat",ios::out|ios::binary); 

    user person; 

    person.ID ="001"; 

    person.password ="abc"; 

    afile.write (reinterpret_cast <const char *>(&person), sizeof (person)); 

    person.ID ="002"; 

    person.password ="def"; 

    afile.write (reinterpret_cast <const char *>(&person), sizeof (person)); 

    afile.close(); 

    afile.open("user.dat",ios::in|ios::binary); 


    while (afile.read (reinterpret_cast <char *>(&person), sizeof (person))) 
    { 
     cout<<person.ID 
      <<" " 
      <<person.password 
      <<endl; 

    } 

} 

Я ожидаю мой консольный вывод, чтобы быть

001 abc 
002 def 

Вместо я получаю

002 def 
002 def 

Может кто-нибудь мне объяснить?

+0

это всегда хорошая идея, чтобы закрыть файл после того, как вы сделали с ним, как и во второй раз вы откройте 'afile'. –

+2

@JonnyHenly, деструктор закрывает его. – chris

+0

Это не сработает. Строка 'std :: string' не является обычным старым объектом данных, и вы не можете сбрасывать их в/из файла таким образом. Вместо этого просмотрите __serialization__. – Blastfurnace

ответ

2

std :: string - это класс, и объект его не сохраняет содержимое строки напрямую.

Это реализация определяется для случая, для простоты, вы можете понять это таким образом:

станд :: строка содержит элемент, который хранит указатель (скажем, PTR) к фактическим данным.

и

std::string s = "001"; 

не будет указывать PTR на адрес строки "001"; он будет выделять память и копировать строку в эту память. Тогда, когда вы делаете

s = "002"; 

не нужно перераспределить память для хранения «002»; он просто копирует «002» в память, которая хранит «001» ранее.

Это означает, что если вы выгрузите необработанные данные строки, она НЕ изменяется.

Когда вы читаете строковые исходные данные, он просто восстановит указатель, который указывает на «002».

надеюсь, что это поможет.

+0

скажите, как это исправить. –

0

Вы храните необработанные данные struct, которые, по сути, содержат только указатели. Таким образом, std::string использует для хранения данных, чтобы изменить размер строки. Единственная причина, по которой ваша программа делает печать любых данных, заключается в том, что в момент чтения объект person все еще существует. Если вы поместите часть чтения вашей программы в отдельную программу, вы не сможете читать какие-либо данные.

Чтобы действительно сохранить ваши данные с помощью fstream, вы можете хранить одну строку в каждой строке, например:

afile << person.ID << endl; 
afile << person.password << endl; 

Файл user.dat:

001 
abc 
002 
def 

И вы можете прочитать это следующим образом:

afile >> person.ID >> person.password; 
while (afile.good()) 
{ 
    cout<<person.ID 
    <<" " 
    <<person.password 
    <<endl; 
    afile >> person.ID >> person.password;  
} 

Вы также должны проверить Serializing a class which contains a std::string.

2

К сожалению, вы не можете сделать это так просто, поэтому вы пишете только указатель на std :: string, а не на то, что содержит строка.Вы можете написать строку в двоичный файл следующим образом:

afile.open("user.dat",ios::out|ios::binary); 

user person; 

person.ID ="001"; 
person.password ="abc"; 

int len = person.ID.size(); 
afile.write(reinterpret_cast<char*>(&len), sizeof(len)); 
afile.write(const_cast<char*>(person.ID.c_str()), len); 

len = person.password.size(); 
afile.write(reinterpret_cast<char*>(&len), sizeof(len)); 
afile.write(const_cast<char*>(person.password.c_str()), len); 

person.ID ="002"; 
person.password ="def"; 

afile.close(); 

И таким образом вы могли прочитать

afile.open("user.dat",ios::in|ios::binary); 

afile.read(reinterpret_cast<char*>(&len), sizeof(len)); 
person.ID.resize(len); 
afile.read(const_cast<char*>(person.ID.c_str()), len); 

afile.read(reinterpret_cast<char*>(&len), sizeof(len)); 
person.password.resize(len); 
afile.read(const_cast<char*>(person.password.c_str()), len); 

cout << person.ID << " " << person.password << endl; 
Смежные вопросы