第九章 文件操作
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第九章文件操作(编程实例与技巧)
void CS9_1View::OnInitialUpdate()
{ CFormView::OnInitialUpdate();
ResizeParentToFit();
CS9_1Doc *pDoc=GetDocument(); //获取CS9_1Doc指针
m_nYear=pDoc->m_nYear; //获取文档中的年份
m_MonthList.SetCurSel(0); //选择一月
m_nCurrentMonth=0; //当前是一月
m_nMonthProduct=pDoc->m_Moth[0].nProduct; //一月产值
m_sNote=pDoc->m_Moth[0].sNote; //一月备注
m_sRiseRate="第一月无此值"; //一月的增值率
CString str;
str.Format("%d",pDoc->m_nTotalProduct);
m_YearProduct.SetCaption(str); //调用CLabelControl设置标题显示年总产值
UpdateData(FALSE); //更新显示
}
void CS9_1View::OnChangeMonthNote() 输入当月备注发生变化(EN_CHANGE)
{
// TODO: If this is a RICHEDIT control, the control will not send this notification unless you override the CFormView::OnInitDialog() function and call CRichEditCtrl().SetEventMask() with the ENM_CHANGE flag ORed into the mask.
CS9_1Doc *pDoc=GetDocument(); //获取CS9_1Doc指针
UpdateData(); //获取最新输入数据
//和文档中的数据比较是否有变化
if(strcmp(pDoc->m_Moth[m_nCurrentMonth].sNote,m_sNote))
{ //记录下新数据
strcpy(pDoc->m_Month[m_nCurrnentMonth].sNote,m_sNote);
pDoc->SetModifiedFlag(); //设置文档变化标志
}
}
void CS9_1View::OnChangeMonthProduct()
{ CS9_1Doc *pDoc=GetDocument(); //获取CS9_1Doc指针
UpdateData(); //获取最新输入数据
//判断数据是否改变
if(pDoc->m_Moth[m_nCurrentMoth].nProduct!=m_nMonthProduct)
{ //改变总产值
pDoc->m_nTotalProduct+=
m_nMonthProduct-pDoc->m_Moth[m_nCurrentMonth].nProduct;
CString str;
str.Format("%d",pDoc->m_nTotalProduct);
m_YearProduct.SetCaption(str); //调用CLabelControl设置标题函数显示年总产值
//记录当月产值到CS9_1Doc中
pDoc->m_Moth[m_nCurrentMonth].nProduct=m_nMonthProduct;
//计算增长率
if(m_nCurrentMonth==0) //是第一月
m_sRiseRate="第一月无此值";
else if(pDoc->m_Moth[m_nCurrentMonth-1].nProduct==0)//前一月产值0
m_sRieRate="上月无产值";
else
m_sRiseRate.Format("%.2f %%",(pDoc->m_Moth[m_nCurrentMonth].nProduct- pDoc->m_Moth[m_nCurrentMonth-1].nProduct)/
(float)(pDoc->m_Moth[m_nCurrentMonth-1].nProduct)*100);
pDoc->SetModifiedFlag(); //设置文档更改标志
UpdateData(FALSE); // 更新显示
}
}
void CS9_1View::OnChangeYear()
{ CS9_1Doc *pDoc=GetDocument(); //获取CS9_1Doc指针
UpdateData(); //获取最新输入
if(pDoc->m_nYear!=m_nYear) //判断数据是否变化
{ pDoc->m_nYear=m_nYear; //记录当月产值到CS9_1Doc中
pDoc->SetModifiedFlag(); //设置文档更改标志
}
}
void CS9_1View::OnDeltaposSpinYear(NMHDR* pNMHDR, LRESULT* pResult)
{ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
//用spin控件更改年份
UpdateData(); //调用它使m_nYear中是最新值
if(pNMUpDown->iDelta>0)&&(m_nYear>0) //减小年份,并且不能小于0
m_nYear--;
else if(pNMUpDown->iDelta<0) //增加年份
m_nYear++;
else //非法输入
{ AfxMessageBox("年份必须是非负整数");
*pResult=0;
return;
}
GetDocument()->m_nYear=m_nYear; //文档记录下新年份
GetDocument()->SetModifiedFlag(); //设置文档更改标志
UpdateData(FALSE);
*pResult = 0;
}
void CS9_1View::OnSelchangeMonth()
{ CS9_1Doc *pDoc=GetDocument(); //获取CS9_1Doc指针
//因每个数据改动,自己都响应了变动的消息,所以不用做保存数据的工作
//获得当前选择的月份并设置正确的显示
m_nCurrentMonth=m_MonthList.GetCurSel();
//计算这个月增长率
if(m_nCurrentMonth==0) //是第一月
m_sRiseRate="第一月无此值";
else if(pDoc->m_Moth[m_nCurrentMonth-1].nProduct==0) //前一月产值0 m_sRiseRate="上月无产值";
else //计算增长率
m_sRiseRate.Format("%.2f%%",(pDoc->m_Moth[m_nCurrentMonth].nProduct- pDoc->m_Moth[m_nCrrentMonth-1].nProduct)/
(float)(pDoc->m_Moth[m_nCurrentMonth-1].nProduct)*100);
m_nMonthProduct=pDoc->m_Moth[m_nCurrentMonth].nProduct; //获得当月产值和备注m_sNote=pDoc->m_Moth[m_nCurrentMonth].sNote;
UpdateData(FALSE);
}
void CS9_1Doc::Serialize(CArchive& ar)
{ if (ar.IsStoring())
{ //实现存储写的代码
ar< ar< for(int i=0;i<12;i++) //循环写入各月信息 { ar< ar.Write(m_Month[i].sNote,50); //这个月备注 } } else { //实现恢复读出的代码 ar>>m_nYear; //读出年份 ar>>m_nTotalProduct; //读出总产值 int nTemp=0; for(int i=0;i<12;i++) //读出各月信息 { ar>>m_Month[i].nProduct; //这个月的产值 if(m_Month[i].nProduct<0) //纠正负值 m_Month[i].nProduct=-m_Month[i].nProduct; nTemp+=m_Month[i].nProduct; //临时统计各月累计总产值 ar.Read(m_Month[i].sNote,50); //读出这个月的备注信息 m_Month[i].sNote[49]=NULL; //确保字符串结束存在! } //进行检查工作 if(nTemp!=m_nTotalProduct) //各月累计和总产值不符 { //提示 AfxMessageBox("该报表文件中总产值与各月总和不符, \\n将总产值置为各月总和!"); m_nTotalProduct=nTemp; //将总产值置为各月总和 } } } void CS9_1Doc::OnCreateText() { CString str; CString filename=GetPathName(); //获取该文档当前的yrp文件名 if(filename.IsEmpty()) //如果空(新建的文件未存之前的情况) filename=GetTitle()+".trp"; //从标题获得 else //改扩展名 filename=filename.Left(filename.GetLength()-3)+"trp"; CStdioFile file; //用CStdioFile创建一个trp文件,注意使用的文件操作标志 if(file.Open(filename,CFile::modeCreate|CFile::modeWrite|CFile::typeText==0)) { str="创建文件"+filename+"失败!"; AfxMessageBox(str); // 创建失败,报告并返回 return; } //实现起来很简单,这就开始写这些文本内容了! str.Format ("%d年产值报告\n\n",m_nYear); //年份 file.WriteString(str); //用WriteString写入 str.Format("总产值:%d元\n\n",m_nTotalProduct); file.WriteString(str); //写总产值文字信息 str.Format("月份: 产值: 单位(元) 备注: \n"); file.WriteString(str); //写各月报表头 for(int i=0;i<12;i++) { //写月产值和备注 str.Format ("%4d%13d %s\n", i+1,m_Month[i].nProduct,m_Month[i].sNote ); file.WriteString(str); } /*好了,文件这就写完了,再作一些辅助工作. 设置文件结尾,因为新创建文件写完后大小就是自己写的内容的大小,所以这条语句不是必须的,只是为演示函数的用法*/ file.SetLength(file.GetPosition()); file.Close(); //关闭文件 str="notepad"+filename; WinExec(str,SW_SHOW); } void CMainFrame::OnFromText() { //选择文本报表文件 CFileDialog dlg(TRUE,"trp",NULL, OFN_HIDEREADONL Y|OFN_OVERWRITEPROMPT, "文本报表文件(*.trp)|*.trp|所有文件(*,*)|*.*||",this); if(dlg.DoModal()==IDCANCEL) return; CString filename=dlg.GetPathName(); //获取选择的文本报表文件名CString str , strTemp; CFile file; //用CFile打开文本报表文件,注意打开的文件方式; if(file.Open(filename,CFile::modeRead)==0) { str="打开文件"+filename+"失败!"; AfxMessageBox(str); //打开失败,报告并返回 return; } //创建CArchive对象,创建方式和文件打开方式要一致 CArchive ar(&file,CArchive::load); //定义yrp文件内容结构(和CS9_1Doc::Serialize的读写顺序一样 struct YRP_STRUCT{ int nYear; //年份 int nTotalProduct; //年总产值 struct{ int nProduct; //月产值 char sNote[50]; //月备注 }Month[12]; //各个月信息 }*pYrpMap; //定义使用报表文件映射的指针 //定义句柄 HANDLE hNewFile=INV ALID_HANDLE_V ALUE; HANDLE hMap=NULL; //获取yrp文件名,这里就使用的是同名的 filename=filename.Left(filename.GetLength()-3)+"yrp"; try { //创建文件句柄,注意创建方式 hNewFile=CreateFile(filename,GENERIC_WRITE|GENERIC_READ, 0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_ARCHIVE,NULL); if(hNewFile==INV ALID_HANDLE_V ALUE) throw"创建报表文件失败!"; //创建内存映射文件句柄,注意和文件的创建方式相一致 hMap=CreateFileMapping(hNewFile,NULL,PAGE_READWRITE,0, sizeof(YRP_STRUCT),"yrp file"); if(hMap==NULL) throw "创建内存映射文件失败!"; //将文件视图映射到内存中,获得指针 pYrpMap=(YRP_STRUCT*)MapViewOfFile(hMap,FILE_MAP_WRITE, 0,0,sizeof(YRP_STRUCT)); if(pYrpMap==NULL) throw "文件视图映射时失败!"; } catch(char *str) {AfxMessageBox(str); //错误报告,并返回 if(hMap!=NULL) CloseHandle(hMap); if(hNewFile!=INV ALID_HANDLE_V ALUE) CloseHandle(hNewFile); return; } //创建工作成功,开始读数据 ar.ReadString(str); sscanf(str,"%d%s",&(pYrpMap->nYear),(LPCTSTR)strTemp); //年份ar.ReadString(str); ar.ReadString(str); sscanf(str,"%s%d%s",(LPCTSTR)strTemp, &(pYrpMap->nTotalProduct),(LPCTSTR)strTemp); //总产值ar.ReadString(str); ar.ReadString(str); for(int i=0;i<12;i++) //各个月的信息 { int nTemp; ar.ReadString(str); sscanf(str,"%d%d%s",&nTemp,&(pYrpMap->Month[i].nProduct), pYrpMap->Month[i].sNote); //没有判断月份的合法性} UnmapViewOfFile(pYrpMap); //解除映射 CloseHandle(hMap); //关闭映射句柄 CloseHandle(hNewFile); //关闭写的文件句柄 ar.Close(); //关闭CArchive file.Close(); //关闭读的文件 //在程序中打开从文本报表中引入的报表文件 if(AfxGetApp()->OpenDocumentFile(filename)==NULL) AfxMessageBox("打开与文本报表同名的报表文件失败!"); }