请问各位一般怎么读写文本文件,如何格式化流?
保存的数据结构大致如下
filetype char t[4] "REF"
Date CTime time "2003-9-2,10:12:11"
Num int count 2048
Data struct{ int x, float y} data[count];
保存时,将数据全用sprintf格式化成字符串,让后用CStdioFile::WriteString()写入文件.
读入文件的时候,发现一个问题.譬如
保存的一行文本为"Date: 2003-9-2,10:12:11",用CStdioFile::ReadString(buf, 199)读入后,需要字符串中把日期提出来. 我用sscanf(buf, "%*6c%d-%d-%d,%d:%d:%d", &year,&mon,&day,&hour,&min,&sec),读入.
总觉得不好.
请问还有别的方法吗?
ps:
记得学c的时候,有fprintf()和fscanf()专门做格式化文本的.
问题点数:100、回复次数:6Top
1 楼nonocast(如果没有如果)回复于 2003-09-02 13:52:29 得分 40
1.其实如果你很熟悉C的话,用fwrite/fread来读写struct应该是很方便的,顺便加上fseek
2.如果是用MFC的话,完全应该用序列化(serialization),MFC中CArchive可以保存和恢复对象。
-----------------------
May you succeed!
------------------------Top
2 楼wolke(子卢)回复于 2003-09-02 14:01:44 得分 0
是啊,我其实是做了个自己的文件结构的。譬如doc类中的int filetype ==1 代表是 REF文件。但输出的时候,希望是文本文件,一行字符串"File type: REF"。所以,用序列化,就很不方便。重载哪个ar? ar<<(CString)str; 会输入一个类标志,结果文本文件显示的结果又不好看。
所以,很烦啊!
有些什么建议吗?Top
3 楼wangjinwang(王者之疯)回复于 2003-09-02 14:06:08 得分 50
关于结构化存储,可以参考下面的代码(测试通过)
/*
序列化就是对数据进行结构化存储,其存取过程都需要类CArchiver的对象
但对于数据,并不要求是不是由CObject派生,甚至是不是类都没关系
*/
class CA
{
public:
char name[9];
BOOL sex;
int age;
CString address;
CTime time;
public:
CA()
{
time=CTime::GetCurrentTime();
}
~CA(){}
public:
void Serialize(CArchive&ar);
};
void CA::Serialize(CArchive&ar)
{
CString text;
// 是不是类无关紧要,函数名是不是Serialize也无关紧要,紧要的只是要有CArchive对象
if(ar.IsStoring())//这个判断是自动进行的,因为创建CArchive对象时指定了是store还是load
{
text=name;//char*不能用(定义成CString就好了)
ar<<text<<sex<<age<<address<<time;
}
else
{
ar>>text>>sex>>age>>address>>time;
strcpy(name,text.GetBuffer(0));
}
}
class CB
{
public:
int index;
CA ca;
public:
CB(){}
~CB(){}
//没有定义Serialize(),但完全可以象CA那样定义
};
void CDialogDlg::OnButtonStore()
{
CB cb;
cb.index=1;
strcpy(cb.ca.name,"王进");
cb.ca.sex=TRUE;
cb.ca.age=30;
cb.ca.address="济南";
CFile file;
if(file.Open("c:\\abc.dat",CFile::modeWrite|CFile::modeCreate))
{
CArchive ar(&file,CArchive::store);
ar<<(cb.index);
cb.ca.Serialize(ar);
//如果CB也定义Serialize,一行调用就可以了,但这两句还是要有(放在Serialize中)
ar.Close();
file.Close();
}
}
void CDialogDlg::OnButtonLoad()
{
CB cb;
CFile file;
if(file.Open("c:\\abc.dat",CFile::modeRead))
{
CArchive ar(&file,CArchive::load);
ar>>cb.index;
cb.ca.Serialize(ar);
//如果CB也定义Serialize,一行调用就可以了,但无论怎么定义,这两行代码还是要有(放在Serialize中)
ar.Close();
file.Close();
}
CString text;
text.Format("%d号\n%s %s %d %s\n%04d-%02d-%02d %02d:%02d:%02d",cb.index,cb.ca.name,cb.ca.sex?"男":"女",cb.ca.age,cb.ca.address,cb.ca.time.GetYear(),cb.ca.time.GetMonth(),cb.ca.time.GetDay(),cb.ca.time.GetHour(),cb.ca.time.GetMinute(),cb.ca.time.GetSecond());
AfxMessageBox(text);
}
Top
4 楼Microsoftadherent(王万新)回复于 2003-09-02 14:17:48 得分 10
对栈里面的数据,不要求从CObject派生,如果是堆里面的,就必须从CObject派生。楼上兄弟的做法不错,比用fread/fwrite要省事多了。Top
5 楼wolke(子卢)回复于 2003-09-02 14:31:10 得分 0
to: wangjinwang(王进)
谢谢。给我上了序列化的一课。
仔细想想,是我自己对问题的描述不够准确。
问题是:文档中的各种数据类型的变量,如何以文本格式存取。写文本是简单的。读的时候很麻烦,因为一个从一个字符串中读入相应变量的值。
Serialize(CArchive &ar)
{
ar << CString(_T("This is a string"));
}
output in file: "This is a string."
hex: "11----------------.""
那个在文本文件中很不好看。Top
6 楼wolke(子卢)回复于 2003-09-02 14:37:58 得分 0
以前对文本文件操作的也不多,查了些资料,这方面相关的也就
sscanf, sprintf,atoi,atof, CStdioFile::ReadString();
要么就是stl里面的了。
所以发个帖子,看看,有没有哪位兄台有这方面(文本文件操作)的经验。
谢谢。Top



