I/O Binary问题。在做通讯录时遇到的保存记录问题。各大侠,求解答啊。。。

neicole 2011-09-17 07:30:48
在做通讯录时遇到的保存记录问题 I/O Binary问题。。
调试了N久,想不出为什么,然后又在网上找了资料,核对了一下自己的格式是否出错,
之后,在程序中编译正常的,到现在,还是想不明这里为什么读取不了二进制文件?
难道是写错了。。。但是又错在哪呢,实在无奈。。。
各大侠,求解答啊。。。

主要的两小段是:

void messageuser::loadhelp(string lfile)
{
std::ifstream rfile;
rfile.open(lfile.c_str(), std::ifstream::in | std::ifstream::binary);
rfile.read((char *) &users, sizeof(users));
rfile.close();
return;
}


void messageuser::savehelp(string fname)
{
std::ofstream sfile;
sfile.open(fname.c_str(), std::ofstream::out | std::ofstream::binary);
sfile.write((char *) & users, users.size());
sfile.close();
return;
}

程序中在尝试一个功能:退出时以进制文件格式保存文件,然后,刚刚进入软件时,读取二进制文件,恢复进度。
问题:保存成功,出现了.dat文件,但是,读取的时候,也成功了,只是,看不见数据在软件里面,当查询用户资料时,显示为空。


...全文
126 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
neicole 2011-09-17
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 gaoyuqi 的回复:]
rfile.read((char *) &users, sizeof(users));
bug
[/Quote]

不太懂,能说得浅白一点吗?不能users这样?
neicole 2011-09-17
  • 打赏
  • 举报
回复
后来,请教老师去了,老师给了我一个回复 rfile.read((char*)users.begin(), users.size() );
之后,我上机,改了一下,一编译,错误,那是个迭代器啊?
于是,我查了一下read的语法,

read 语法:
istream &read( char *buffer, streamsize num );
函数read()用于输入流,在将字符放入buffer 之前从流中读取num 个字节。如果碰到EOF,read()中止,丢弃不论多少个字节已经放入。例如:
struct {
int height;
int width;
} rectangle;

input_file.read( (char *)(&rectangle), sizeof(rectangle) );
if( input_file.bad() ) {
cerr << "Error reading data" << endl;
exit( 0 );
}
write 语法:

ostream &write( const char *buffer, streamsize num );
write()函数用于输出流,从buffer中写num个字节到当前输出流中。

这次,我终于想明白了很多了,原来那个迭代的思路是有点对的,但是,在这里实现不了,在messageuser类中,
没有构造map,它是一个空容器,哪里会有地址可以让它放入呢?再说,map.begin()是不能放入数据的,得通过map.insert()函数,
所以,这就形成一个bug了,想了几个方法,创建新容器。。。失败,最后,还是用输入输出流解决问题了,将savehelp的函数改了一下,
将loadhelp的函数改了一下,最后,再将load()函数改了一下,这样一下,程序就完成了,剩下要做的就是给自己的程序写写说明了。
上来CSDN,最后还是自己给自己回答了,晕啊~~


/**
* bool messageuser::savedhelp();保存文件为二进制文件,若保存文件失败,则返回false;
* void messageuser::save(); 按要求输入保存文件的名称,完成保存文件功能。
*/
void messageuser::savehelp(string fname)
{
std::ofstream sfile;
sfile.open(fname.c_str(), std::ofstream::out | std::ofstream::binary);
type_map_si::iterator iter = users.begin();
while(iter != users.end() )
{
sfile << iter -> first << "\t\t" << iter -> second << " ";
++iter;
}
sfile.close();
return;
}

void messageuser::save()
{
using std::fstream;
using std::ofstream;
using std::ifstream;
using std::cout;
using std::cin;
fstream inout(savefilename.c_str(), fstream::out | fstream::in);
inout.close();
string sname("");
string comparen("");
char choice('r');
bool circulateInput;
bool circulateInput2;
cout << "请输入需要保存的文件名:";
do
{
inout.open(savefilename.c_str(), fstream::out | fstream::in);
circulateInput = false;
cin >> sname;
sname.append(".dat");
while( inout >> comparen )
// 文件名核对,是否有重名现象
if (comparen == sname)
{
cout << "\n注意,检测到已存在同名文件名。";
cout << std::unitbuf << "\n覆盖请按 " << "y"
<< " 否则请按 \"r\" 重新键入文件名:" << std::nounitbuf;
do
{
circulateInput2 = false;
cin >> choice;
while(!cin)
{
cin.clear();
cin.sync();
std::cerr << "\n输入错误,请重新输入选择:";
cin >> choice;
}
switch(choice)
{
case 'r': circulateInput = true;break;
case 'y': break;
default:
{
std::cerr << "\n输入错误,请重新输入选择:";
cin >> choice;
circulateInput2 = true;
break;
}
}
}while(circulateInput2);
}
inout.clear();
inout.close();
}while(circulateInput);
if (choice == 'r')
{
cout << "接受测试";
string cr(" ");
inout.open(savefilename.c_str(), fstream::out | fstream::in | fstream::app);
inout << sname << cr ;
inout.close();
}
savehelp(sname);
cout << "\n恭喜,文件保存成功!";
cout << std::endl;
return;
}

/**
* bool messageuser::loadhelp();检测是否已存在已保存的文件,若存在,则返回true;
* void messageuser::load(); 完成文件读取功能。
*/
void messageuser::loadhelp(string lfile)
{
std::ifstream rfile;
string temp;
int itemp;
rfile.open(lfile.c_str(), std::ifstream::in | std::ifstream::binary);
type_map_si::iterator iter = users.begin();
while(!rfile.eof())
{
rfile >> temp >> itemp;
users[temp] = itemp;
}
rfile.close();
return;
}

void messageuser::load()
{
using std::cout;
using std::cin;
using std::ifstream;
int i(0);
string ofile;
cout << "\n\n正在读取已存储的通讯录文件列表...\n";
std::set<string> TempSaveName;
ifstream reado;
reado.open(savefilename.c_str(), ifstream::in);
if (reado.good())
{
while(!reado.eof())
{
reado >> ofile;
TempSaveName.insert(ofile);
if(!reado)
; // if控制,防止多读取一次最后的空格,但是读取不到任何字符.
// 在文件中的格式为abc cba ,每个文件后都会有一个空格
else
{
cout << "\n" << ++i << ". "<< ofile;
}
}
cout << "\n\n请输入需要读取的文件名称,若不需读取,读输入\"no\":";
cin >> ofile;
if (TempSaveName.count(ofile) )
{
loadhelp(ofile);
cout << "\n读取成功!\n";
}
else if (ofile == "no")
{
cout << "\n操作成功!\n";
}
else
{
cout << "\n读取失败,请检查需要读取的文件的名字是否输入正确!"
<< "\n 还有一次输入机会,若输入错误,将直接进入系统:";
cin >> ofile;
if (TempSaveName.count(ofile) )
{
loadhelp(ofile);
cout << "\n读取成功!\n";
}
else if (ofile == "no")
{
cout << "\n操作成功!\n";
}
else
{
cout << "\n将直接进入系统操作。。。\n";
}
}
}
else
{
reado.clear();
cout << "\n尚未发现已存储的通讯文件。\n";
}
reado.close();
}
gaoyuqi 2011-09-17
  • 打赏
  • 举报
回复
rfile.read((char *) &users, sizeof(users));
bug
neicole 2011-09-17
  • 打赏
  • 举报
回复
先去练车,一回到宿舍就开电脑~~ 关注此问题
当然,自己还会继续找原因,在想会不会是跟load()函数有关??还是保存的时候虽然保存出.dat ,但是里面的内容是空,有没有可能呢?
思路有点不清晰,出现问题的原因是在哪呢?
neicole 2011-09-17
  • 打赏
  • 举报
回复

// main.cpp -- 通讯录小项目设计

/**
* 通讯录小项目设计
* 【基本要求】
* (1) 设每个记录有下列数据项:电话号码、用户名;
* (2) 从键盘输入各记录,分别以用户名为关键字建立map容器;
* (3) 可通过关键字查找,如:一个名字中含有“A”的全部人的信息,再加上一个退出系统保留信息功能。
* (4)显示给定电话号码的记录;
* (5)通讯录信息文件保存,下次打开程序时,可直接读取已保存的通讯录。
**/

#include <iostream>
#include <cstdlib> // system("cls")
#include <conio.h> // _getch()
#include "messageuser.h"
using std::cout;
using std::cin;
using std::endl;

char enterchar(char, char); // 输入错误时要求重新输入
void next(); // 进行下一步时的提醒操作
char showmenu(); // 显示主菜单

int main()
{
messageuser mes;
cout << "*************************** 欢迎来到通讯录管理软件 ***************************";
mes.load();
next();
char choice;
do
{
choice = showmenu();
switch(choice)
{
case '1': // 1. 添加新用户
{
mes.insertin();
next();
break;
}
case '2': // 2. 查找用户资料
{
mes.find();
next();
break;
}
case '3': // 3. 删除用户及相关资料
{
mes.del();
next();
break;
}
case '4': // 4. 保存现有的全部用户资料
{
mes.save();
next();
break;
}
case '5': // 5. 显示通讯录中全部用户资料
{
cout << '\n';
mes.printout();
next();
break;
}
case '6': // 6. 退出通讯录管理软件
{
cout << "\n O(∩_∩)O~~ 恭喜您,已成功退出系统。";
next();
break;
}
}
}while(choice != '6');
return 0;
}

char showmenu() // 显示主菜单
{
system("cls");
cin.sync();
cout << "*************************** 欢迎来到通讯录管理软件 ***************************\n"
<< "* *\n"
<< "* 1. 添加新用户 *\n"
<< "* 2. 查找用户资料 *\n"
<< "* 3. 删除用户及相关资料 *\n"
<< "* 4. 保存现有的全部用户资料 *\n"
<< "* 5. 显示通讯录中全部用户资料 *\n"
<< "* 6. 退出通讯录管理软件 *\n\n"
<< "--> 我的选择(填数字):";
return enterchar('1', '7');
}

char enterchar(char min, char max) // 输入错误时要求重新输入
{
char choice;
bool circulate(false);
do
{
do
{
cin >> choice;
circulate = false;
if (!cin)
{
std::cerr << "\n您的输入有误,请重新输入:";
circulate = true;
cin.sync();
cin.clear();

}
}while(circulate);
circulate = false;
if(!(choice >= min && choice < max))
{
std::cerr << "\n您的输入有误,请重新输入:";
circulate = true;
cin.clear();
cin.sync();
}
}while(circulate);
return choice;
}

void next() // 进行下一步时的提醒操作
{
cout << "\n请按任意键继续...\n";
char temp(_getch());
return;
}



// messageuser.h -- 实现电话簿全部相关功能

/*
* 数据成员: map<string, int> users; // 使用关联容器map类型高效地查找电话号码
* 成员函数: 主要有五个,分别可以实行添加,删除,输出,保存,读取的功能。
*/

#ifndef USER_H_
#include <iostream>
#include <string>
#include <utility>
#include <map>
using std::string;

class messageuser
{
private:
typedef std::map<string,int> type_map_si;
string savefilename;
type_map_si users;

bool inserthelp(string, int);
bool findAllHelp(string);
bool findSingleHelp(string, type_map_si &);
bool deletehelp(string);
void savehelp(string);
void loadhelp(string);

public:
messageuser():savefilename("通讯录保存文件列表.txt"){}
void insertin();
void find();
void del();
void printout();
void save();
void load();
};
#endif
neicole 2011-09-17
  • 打赏
  • 举报
回复
以下是程序全部代码

// messageuser.cpp -- 实现电话簿全部相关功能

/*
* 数据成员: map<string, int> users; // 使用关联容器map类型高效地查找电话号码
* 成员函数: 主要有五个,分别可以实行添加,删除,输出,保存,读取的功能。
*/
#include "messageuser.h"
#include <iostream>
#include <string>
#include <utility>
#include <map>
#include <fstream>
using std::string;

/** 添加函数
* bool inserthelp(string, int)
* 帮助插入操作:有一个函数帮助插入,第一个形参是用户名,第二个形参是电话号码。
* void insertin();
* 可以直接调用的公有函数,函数会提示有多少个需要插入的元素,根据插入成功失败进行相关提示。
*/
bool messageuser::inserthelp(string stemp, int itemp)
{
// users.insert(make_pair(stemp, itemp));
users.insert(type_map_si::value_type(stemp, itemp));
return true;
}

void messageuser::insertin()
{
using std::cout;
using std::cin;
using std::endl;

// 用户增加数目
cout << endl << "请输入需要增加的用户数目:";
int ntemp;
cin >> ntemp;
while(!cin)
{
cout << "\n输入错误,请重新输入:";
cin.sync();
cin.clear();
cin >> ntemp;
}

// 输入用户名及号码
int itemp;
string stemp;
for (int i = 0; i != ntemp; i++)
{
cout << endl << "请输入需要增加的第 " << i + 1 << " 位用户名:";
cin >> stemp;
if (findAllHelp(stemp))
{
std::cerr << "\n输入错误,这位用户的相关资料已存在,请重新输入需要添加的不重复用户:";
cin >> stemp;
}
cout << endl << "请输入需要增加的第 " << i + 1 << " 位用户的电话号码:";
cin >> itemp;
while(!cin)
{
cout << "\n输入错误,请重新输入这位用户的电话号码:";
cin.sync();
cin.clear();
cin >> itemp;
}
if(inserthelp(stemp, itemp))
;
else
{
cout << "\n该用户添加失败,有可能是用户名已存在,停止本次添加操作。";
return;
}
}
cout << "\n该用户组添加成功。";
cin.sync();
cin.clear();
cout << endl;
return;
}

/** 查找函数
* bool findAllhelp(string) 寻找用户名是否在该类的数据成员中,如果用户名完全匹配时则返回true.
* bool findSingleHelp(string) 寻找用户名是否在该类的数据成员中,如果用户名有匹配字符时则返回true.
* void find() 实现查找功能,函数会提示输入需要查找的元素名称并返回相关结果。
*/

bool messageuser::findAllHelp(string findname)
{
if ( users.empty() )
return false;
if ( users.find(findname) == users.end() )
return false;
else
return true;
}

bool messageuser::findSingleHelp(string findname, type_map_si & tsave)
{
// 这里需要补充
string::size_type fnameSize( findname.size());
string::size_type fnum(0);
string::size_type tnum(0);
string::size_type tnameSize;
type_map_si::iterator truename = users.begin();
while(truename != users.end())
{
tnameSize = (truename -> first).size();
// 容器中每个用户名与输入的姓名作对比
do
{
if( findname[fnum] == (truename -> first)[tnum] )
{
if( fnum + 1 == fnameSize)
{ // 符合条件,添加元素进新容器
tsave[truename -> first] = truename -> second;
break;
}
else
{
++fnum;
++tnum;
// if (fnum > fnameSize) break;
}
}
else
{
if (fnum == 0)
{
++tnum;
}
else if ( fnum + 1 == fnameSize)
{
break;
}
else
{
++tnum;
}
}
}while(tnum != tnameSize + 1);
fnum = 0;
tnum = 0;
++truename;
}
if ( tsave.end() == tsave.begin() )
return false;
else
return true;
}

void messageuser::find()
{
using std::cin;
using std::cout;
using std::endl;
string fname;
type_map_si tempToPrint;
cout << "\n请输入需要查找的姓名:";
cin >> fname;
if ( findAllHelp(fname) ) // 全名符合的用户资料
{
cout << "\n恭喜,找到" << fname << " 的记录,电话号码为 " << users[fname] << endl;
}
else if ( findSingleHelp(fname, tempToPrint) ) // 有相关字符符合名字的用户资料
{
cout << "\n恭喜,找到 " << tempToPrint.size() << " 个相匹配的用户名。\n\n";
type_map_si::iterator tprint = tempToPrint.begin();
int sum(0);
cout << " 姓名\t 号码\n";
while(tprint != tempToPrint.end())
{
cout << tprint -> first << "\t" << tprint -> second << endl;
++tprint;
++sum;
}
cout << "\n已成功输出 " << sum << " 名用户资料\n";
}
else
{
cout << "\n对不起,未找到需要搜索的用户。" << endl;
}
return;
}

/** 删除函数
* bool deletehelp(string) 寻找用户名是否在该类的数据成员中,如果用户删除成功则返回true.
* void del() 实现删除功能时,函数会提示输入需要删除的元素,首先调用find函数判断是否存在元素,再进行相关操作,返回相关结果。
*/

bool messageuser::deletehelp(string dname)
{
if ( users.empty() )
return false;
if( users.erase(dname))
return true;
else
return false;
}

void messageuser::del()
{
using std::cout;
using std::cin;
using std::endl;
string dname;
cout << "\n请输入需要删除的资料的姓名:";
cin >> dname;
if( 0 == findAllHelp(dname) )
{
cout << "\n未找到该用户的资料,请核实后再进行操作。";
return;
}
if ( 0 == deletehelp(dname) )
{
cout << "\n意外,删除失败。";
}
else
{
cout << "\n恭喜,删除 " << dname << " 用户资料成功。";
}
return;
}

/** 打印函数
* void printout() 打印全部用户资料。
*/

void messageuser::printout()
{
using std::cin;
using std::cout;
using std::endl;
type_map_si::iterator iter = users.begin();
if ( iter == users.end() )
{
cout << "此通讯录为空。\n";
return;
}

int sum(0); // 用以统计用户数目
cout << " 姓名\t 号码\n";
while(iter != users.end() )
{
cout << iter -> first << "\t" << iter -> second << endl;
++sum;
++iter;
}
cout << "\n已成功输出 " << sum << " 名用户资料\n";
return;
}


/**
* bool messageuser::savedhelp();保存文件为二进制文件,若保存文件失败,则返回false;
* void messageuser::save(); 按要求输入保存文件的名称,完成保存文件功能。
*/
void messageuser::savehelp(string fname)
{
std::ofstream sfile;
sfile.open(fname.c_str(), std::ofstream::out | std::ofstream::binary);
sfile.write((char *) & users, users.size());
sfile.close();
return;
}

void messageuser::save()
{
using std::fstream;
using std::ofstream;
using std::ifstream;
using std::cout;
using std::cin;
fstream inout(savefilename.c_str(), fstream::out | fstream::in);
inout.close();
string sname("");
string comparen("");
char choice('r');
bool circulateInput;
bool circulateInput2;
cout << "请输入需要保存的文件名:";
do
{
inout.open(savefilename.c_str(), fstream::out | fstream::in);
circulateInput = false;
cin >> sname;
sname.append(".dat");
while( inout >> comparen )
// 文件名核对,是否有重名现象
if (comparen == sname)
{
cout << "\n注意,检测到已存在同名文件名。";
cout << std::unitbuf << "\n覆盖请按 " << "y"
<< " 否则请按 \"r\" 重新键入文件名:" << std::nounitbuf;
do
{
circulateInput2 = false;
cin >> choice;
while(!cin)
{
cin.clear();
cin.sync();
std::cerr << "\n输入错误,请重新输入选择:";
cin >> choice;
}
switch(choice)
{
case 'r': circulateInput = true;break;
case 'y': break;
default:
{
std::cerr << "\n输入错误,请重新输入选择:";
cin >> choice;
circulateInput2 = true;
break;
}
}
}while(circulateInput2);
}
inout.clear();
inout.close();
}while(circulateInput);
if (choice == 'r')
{
cout << "接受测试";
string cr(" ");
inout.open(savefilename.c_str(), fstream::out | fstream::in | fstream::app);
inout << sname << cr ;
inout.close();
}
savehelp(sname);
cout << "\n恭喜,文件保存成功!";
cout << std::endl;
return;
}

/**
* bool messageuser::loadhelp();检测是否已存在已保存的文件,若存在,则返回true;
* void messageuser::load(); 完成文件读取功能。
*/
void messageuser::loadhelp(string lfile)
{
std::ifstream rfile;
rfile.open(lfile.c_str(), std::ifstream::in | std::ifstream::binary);
rfile.read((char *) &users, sizeof(users));
rfile.close();
return;
}

void messageuser::load()
{
using std::cout;
using std::cin;
using std::ifstream;
int i(0);
string ofile;
cout << "\n\n正在读取已存储的通讯录文件列表...\n";
ifstream reado;
reado.open(savefilename.c_str(), ifstream::in);
if (reado.good())
{
while(!reado.eof())
{
reado >> ofile;
if(!reado)
; // if控制,防止多读取一次最后的空格,但是读取不到任何字符.
// 在文件中的格式为abc cba ,每个文件后都会有一个空格
else
{
cout << "\n" << ++i << ". "<< ofile;
}
}
cout << "\n\n请输入需要读取的文件名称:";
cin >> ofile;
////////////////
reado.close();
loadhelp(ofile);
cout << "\n读取成功!\n";
}
else
{
reado.clear();
cout << "\n尚未发现已存储的通讯文件。\n";
}

}


65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧