单文档程序 文档保存的问题:文档莫名其妙被清空了。

善良超锅锅 2014-05-26 03:55:05
写了一个矢量图形绘制程序。基于SDI。我需要保存数据,而且要保存为特定的格式。不想用mfc本身提供的序列化。

为了自定义文件的格式。我重载了文档类的OnOpenDocument函数和OnSaveDocument(LPCTSTR lpszPathName)函数。代码如下

BOOL CToyDrawDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;

// TODO: 在此添加您专用的创建代码
m_GraphList.Load(Unicode2ANSI(lpszPathName));
return TRUE;
}


BOOL CToyDrawDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
// TODO: 在此添加专用代码和/或调用基类
m_GraphList.Save(Unicode2ANSI(lpszPathName));

return CDocument::OnSaveDocument(lpszPathName);
}

在OnSaveDocument函数中根据传入的文件名创建文件,写入格式化数据,关闭文件。再调用基类的OnSaveDocument函数。
在OnOpenDocument函数中根据传入的文件名打开文件,载入数据,然后调用基类的OnOpenDocument函数。


下面是我测试的:3个用例,其中用例3出现了问题:
用例1:打开软件-->在默认创建视图中绘图,写入数据--.>保存文件。(会弹出文件对话框)
结果:文件是正确的,我用浏览器和notepad++打开看,很完美。

用例2:打开软件-->绘图--->保存文件-->接着绘图---->再按ctrl+S保存文件。
结果:文件还是正确的,后面绘制的数据也看到了。第一次保存会弹出一个文件对话框。后面就没有了。

用例3:打开软件-->打开前面保存的文件-->文件中的数据正常显示在视图上--->在这个基础上绘图、或修改。-->ctrl+s保存文件。
结果:打开文件,发现文件被清空了。大小为0KB,里面任何数据都没有。这是为什么呢?

上面3个用例都用到了保存文件的功能,为什么3的文件不能正常保存呢?我调试时发现它们都会执行OnSaveDocument函数。难道它们的执行逻辑不同吗?
要自定义文件格式,正确的步骤不是这样的吗?
...全文
141 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
u010540481 2014-08-10
  • 打赏
  • 举报
回复
楼主问题怎么解决的? 我也遇到文件被清空的问题。
善良超锅锅 2014-05-27
  • 打赏
  • 举报
回复
引用 6 楼 cvbtvbwu 的回复:
我也做过类似的东西。在单文档里保存数据,读取数据。我的方法是:在界面上给两个按钮,一个打开按钮,一个保存按钮,点击打开按钮的时候,打开文件对话框选择文件路径,然后自己
	CFile mFile; 

	if (mFile.Open(szPath, CFile::modeRead))
	{
		CArchive arch(&mFile,CArchive::load);

		//////////////////////////////////////////////////
		int nDataVersion;
		arch>>nDataVersion;

		......

		//////////////////////////////////////////////////
		arch.Close();

		mFile.Close();

		return TRUE;
	}
	else
	{
		return FALSE;
	}
这样去读取文件,然后调用视图去更新界面,视图就会用新的数据去绘图界面。点击打开按钮的时候,打开文件对话框选择文件保存路径,然后自己

CFile mFile; 

	if (mFile.Open(szPath, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite))
	{
		CArchive arch(&mFile,CArchive::store);

		//////////////////////////////////////////////////

		arch<<DEF_DATA_VERSION;

		......

		//////////////////////////////////////////////////
		arch.Close();

		mFile.Close();

		return TRUE;
	}
	else
	{
		return FALSE;
	}
,去保存数据文件,这过程,没有涉及到什么重载了文档类的OnOpenDocument函数和OnSaveDocument(LPCTSTR lpszPathName)函数,我也不知道它们有什么用,反正我一直就这样过来的,也一直能完成这事情
这样好蹩脚。我这个是毕设,不能让老师看扁了。我想表现的自然些。我的问题解决了。你可以根据我的问题和这里的几个答案学习一下,用框架自带保存打开接口挺好的。
躺着睡的蜗牛 2014-05-26
  • 打赏
  • 举报
回复
改成下面的试试

BOOL CToyDrawDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
    // TODO: 在此添加专用代码和/或调用基类
    m_GraphList.Save(Unicode2ANSI(lpszPathName));
     
    return TRUE;
}
caewow 2014-05-26
  • 打赏
  • 举报
回复
对的,你这样直接自己写好了,没必要再去调用基类的函数了
叶恭介叶恭介 2014-05-26
  • 打赏
  • 举报
回复
我也做过类似的东西。在单文档里保存数据,读取数据。我的方法是:在界面上给两个按钮,一个打开按钮,一个保存按钮,点击打开按钮的时候,打开文件对话框选择文件路径,然后自己
	CFile mFile; 

	if (mFile.Open(szPath, CFile::modeRead))
	{
		CArchive arch(&mFile,CArchive::load);

		//////////////////////////////////////////////////
		int nDataVersion;
		arch>>nDataVersion;

		......

		//////////////////////////////////////////////////
		arch.Close();

		mFile.Close();

		return TRUE;
	}
	else
	{
		return FALSE;
	}
这样去读取文件,然后调用视图去更新界面,视图就会用新的数据去绘图界面。点击打开按钮的时候,打开文件对话框选择文件保存路径,然后自己

CFile mFile; 

	if (mFile.Open(szPath, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite))
	{
		CArchive arch(&mFile,CArchive::store);

		//////////////////////////////////////////////////

		arch<<DEF_DATA_VERSION;

		......

		//////////////////////////////////////////////////
		arch.Close();

		mFile.Close();

		return TRUE;
	}
	else
	{
		return FALSE;
	}
,去保存数据文件,这过程,没有涉及到什么重载了文档类的OnOpenDocument函数和OnSaveDocument(LPCTSTR lpszPathName)函数,我也不知道它们有什么用,反正我一直就这样过来的,也一直能完成这事情
lis2012 2014-05-26
  • 打赏
  • 举报
回复
引用 楼主 shimachao 的回复:
写了一个矢量图形绘制程序。基于SDI。我需要保存数据,而且要保存为特定的格式。不想用mfc本身提供的序列化。 为了自定义文件的格式。我重载了文档类的OnOpenDocument函数和OnSaveDocument(LPCTSTR lpszPathName)函数。代码如下
BOOL CToyDrawDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;

	// TODO:  在此添加您专用的创建代码
	m_GraphList.Load(Unicode2ANSI(lpszPathName));
	return TRUE;
}


BOOL CToyDrawDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
	// TODO: 在此添加专用代码和/或调用基类
	m_GraphList.Save(Unicode2ANSI(lpszPathName));
	
	return CDocument::OnSaveDocument(lpszPathName);
}
在OnSaveDocument函数中根据传入的文件名创建文件,写入格式化数据,关闭文件。再调用基类的OnSaveDocument函数。 在OnOpenDocument函数中根据传入的文件名打开文件,载入数据,然后调用基类的OnOpenDocument函数。 下面是我测试的:3个用例,其中用例3出现了问题: 用例1:打开软件-->在默认创建视图中绘图,写入数据--.>保存文件。(会弹出文件对话框) 结果:文件是正确的,我用浏览器和notepad++打开看,很完美。 用例2:打开软件-->绘图--->保存文件-->接着绘图---->再按ctrl+S保存文件。 结果:文件还是正确的,后面绘制的数据也看到了。第一次保存会弹出一个文件对话框。后面就没有了。 用例3:打开软件-->打开前面保存的文件-->文件中的数据正常显示在视图上--->在这个基础上绘图、或修改。-->ctrl+s保存文件。 结果:打开文件,发现文件被清空了。大小为0KB,里面任何数据都没有。这是为什么呢? 上面3个用例都用到了保存文件的功能,为什么3的文件不能正常保存呢?我调试时发现它们都会执行OnSaveDocument函数。难道它们的执行逻辑不同吗? 要自定义文件格式,正确的步骤不是这样的吗?
可以看出 3中m_GraphList里面的数据不正确或者为空,导致了后边数据没能存入
善良超锅锅 2014-05-26
  • 打赏
  • 举报
回复
引用 3 楼 schlafenhamster 的回复:
“很多都要调用基类的函数” 是, 那是因为 基类 还有事 要干, 你 都 干 完了 , 就 不必 调 基类了。
果然是这样。可是上次我删掉后出了问题。可能是其他地方的问题吧。我好二。
schlafenhamster 2014-05-26
  • 打赏
  • 举报
回复
“很多都要调用基类的函数” 是, 那是因为 基类 还有事 要干, 你 都 干 完了 , 就 不必 调 基类了。
善良超锅锅 2014-05-26
  • 打赏
  • 举报
回复
引用 1 楼 schlafenhamster 的回复:
都自己 读写了, 为什么 要调用 基类 函数 ?
之前我把基类的函数调用删除了。发现不调用的话,有些功能用不了。有异常。我再看看去行不行。 MFC里重载函数,不是很多都要调用基类的函数吗?
schlafenhamster 2014-05-26
  • 打赏
  • 举报
回复
都自己 读写了, 为什么 要调用 基类 函数 ?
网管教程 从入门到精通软件篇 ★一。★详细的xp修复控制台命令和用法!!! 放入xp(2000)的光盘,安装时候选R,修复! Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的诊断和测试以及恢复系统功能的工具。小编的确一直都想把这方面的命令做个总结,这次辛苦老范给我们整理了这份实用的秘笈。   Bootcfg   bootcfg 命令启动配置和故障恢复(对于大多数计算机,即 boot.ini 文件)。   含有下列参数的 bootcfg 命令仅在使用故障恢复控制台时才可用。可在命令提示符下使用带有不同参数的 bootcfg 命令。   用法:   bootcfg /default  设置默认引导项。   bootcfg /add    向引导列表中添加 Windows 安装。   bootcfg /rebuild  重复全部 Windows 安装过程并允许用户选择要添加的内容。   注意:使用 bootcfg /rebuild 之前,应先通过 bootcfg /copy 命令备份 boot.ini 文件。   bootcfg /scan    扫描用于 Windows 安装的所有磁盘并显示结果。   注意:这些结果被静态存储,并用于本次会话。如果在本次会话期间磁盘配置发生变化,为获得更新的扫描,必须先重新启动计算机,然后再次扫描磁盘。   bootcfg /list   列出引导列表中已有的条目。   bootcfg /disableredirect 在启动引导程序中禁用重定向。   bootcfg /redirect [ PortBaudRrate] |[ useBiosSettings]   在启动引导程序中通过指定配置启用重定向。   范例: bootcfg /redirect com1 115200 bootcfg /redirect useBiosSettings   hkdsk   创建并显示磁盘的状态报告。Chkdsk 命令还可列出并纠正磁盘上的错误。   含有下列参数的 chkdsk 命令仅在使用故障恢复控制台时才可用。可在命令提示符下使用带有不同参数的 chkdsk 命令。   vol [drive:] [ chkdsk [drive:] [/p] [/r]   参数  无   如果不带任何参数,chkdsk 将显示当前驱动器中的磁盘状态。 drive: 指定要 chkdsk 检查的驱动器。 /p   即使驱动器不在 chkdsk 的检查范围内,也执行彻底检查。该参数不对驱动器做任何更改。 /r   找到坏扇区并恢复可读取的信息。隐含着 /p 参数。   注意 Chkdsk 命令需要 Autochk.exe 文件。如果不能在启动目录(默认为 %systemroot%System32)中找到该文件,将试着在 Windows 安装 CD 中找到它。如果有多引导系统的计算机,必须保证是在包含 Windows 的驱动器上使用该命令。 Diskpart   创建和删除硬盘驱动器上的分区。diskpart 命令仅在使用故障恢复控制台时才可用。   diskpart [ /add |/delete] [device_name |drive_name |partition_name] [size]   参数 无   如果不带任何参数,diskpart 命令将启动 diskpart 的 Windows 字符模式版本。   /add   创建新的分区。   /delete   删除现有分区。   device_name   要创建或删除分区的设备。设备名称可从 map 命令的输出获得。例如,设备名称:   DeviceHardDisk0   drive_name   以驱动器号表示的待删除分区。仅与 /delete 同时使用。以下是驱动器名称的范例:   D:   partition_name   以分区名称表示的待删除分区。可代替 drive_name 使用。仅与 /delete 同时使用。以下是分区名称的范例:   DeviceHardDisk0Partition1    大小   要创建的分区大小,以兆字节 (MB)表示。仅与 /add 同时使用。   范例   下例将删除分区: diskpart /delete Device HardDisk0 Partition3 diskpart /delete F:   下例将在硬盘上添加一个 20 MB 的分区:   diskpart /add Device HardDisk0 20   Fixboot

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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