电脑常规操作-《VC ANSI环境下按行读取ANSI等四种文本文件》.docx_第1页
电脑常规操作-《VC ANSI环境下按行读取ANSI等四种文本文件》.docx_第2页
电脑常规操作-《VC ANSI环境下按行读取ANSI等四种文本文件》.docx_第3页
电脑常规操作-《VC ANSI环境下按行读取ANSI等四种文本文件》.docx_第4页
电脑常规操作-《VC ANSI环境下按行读取ANSI等四种文本文件》.docx_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

VC ANSI环境下按行读取ANSI、UNICODE 、UNICODE big endian、UTF-8四种文本文件1.问题提出MFC提供的文件类CStdioFile,其中一个函数ReadString实现了文件的按行读取,但是不能满足不同类型的文本文件的按行读取,为了解决这一问题,笔者初步研究了一些编码知识,参考了网上的一些资料,实现了CStdioFile类的扩展类CStdioFileEx,完成了常见文本文件的按行读取(注明:不包括DOC、PDF等其他形式的文档).在此对网上分享编码经验的网友表示感谢,同时由于我编写的类还未经过严格测试,如有错误或方法过于复杂敬请各位指正。2.问题解决(1)四种常见文本文件编码方式研究ANSI、UNICODE 、UNICODE big endian、UTF-8四种格式编码存在差别,简要介绍如下:ANSI编码:无文件头(文件编码开头标志性字节) ANSI编码字母数字占一个字节,汉字占两个字节,回车换行符 单字节 十六进制表示为0d 0aUNICODE编码:文件头,十六进制表示为FF FE每一个字符都用两个字节编码回车换行符 双字节 000d 000aUnicode big endian编码:文件头十六进制表示为FE FF ,后面编码是把字符的高位放在前面,低位放在后面,正好和Unicode编码颠倒。回车换行符,双字节,十六进制表示为0d00 0a00UTF-8 编码:文件头,十六进制表示为EF BB BF。UTF-8是Unicode的一种变长字符编码,数字、字母、回车、换行都用一个字节表示,汉字占3个字节.回车换行符,单字节,十六进制表示为0d 0a以中文你好二字为例,各种类型的编码对应的十六进制格式(可由EditPlus查看)如下图所示:由此可见上述的探讨是正确的。(2)按行读取上述四种格式文本文件的解决方案针对不同文件编码的特点,通过先检测文件头判断文件编码类型,然后根据文件类型分别调用不同的读取函数实现文件的按行读取。按行读取过程如下图所示:实现过程中,编写CStdioFileEx类,该类继承自CStdioFile类,覆盖了CStdioFile类的BOOL ReadString(CString& rString)方法,从而实现了文件按行读取。(3)CStdioFileEx类的实现代码代码清单:cpp view plaincopyprint?1. /StdioFileEx.h:interfacefortheCStdioFileExclass. 2. / 3. / 4. 5. #if!defined(AFX_STDIOFILEEX_H_C1F1F96B_9417_4388_8D24_892EDFA2A616_INCLUDED_) 6. #defineAFX_STDIOFILEEX_H_C1F1F96B_9417_4388_8D24_892EDFA2A616_INCLUDED_ 7. 8. #if_MSC_VER1000 9. #pragmaonce 10. #endif/_MSC_VER1000 11. /- 12. /程序用途:按行读取常见(包括ANSI、UNICODE、UNICODEbigendian、UTF-8)格式的文本文件 13. /程序作者:湖北师范学院计算机科学与技术学院王定桥 14. /核心算法:CStdioFileEx继承自CStdioFile,覆盖CStdioFile的BOOLReadString(CString&rString)方法, 15. /根据不同文件编码特征,寻找文件回车换行符判断读取行结束,文件结束符判断文件结束 16. /检测不同文件编码头部,获取文件类型后调用不同的读取函数 17. /测试结果:在Windows7VC6.0环境下测试上述四种格式的txt文件通过 18. /尚未完成:未重载CStdioFile的virtualLPTSTRReadString(LPTSTRlpsz,UINTnMax)方法 19. /未完成WriteString方法,未在VCUNICODE环境下的测试 20. /制作时间:2012-04-19 21. /代码版权:代码公开供学习交流使用欢迎指正错误改善算法 22. /- 23. #includestdafx.h 24. /文本文件类型枚举值 25. typedefenumTextCodeType26. 27. UTF8=0,28. UNICODE=1,29. UNICODEBIGENDIAN=2,30. ANSI=3,31. FILEERROR=432. TextCode;33. classCStdioFileEx:publicCStdioFile34. 35. public:36. CStdioFileEx();37. CStdioFileEx(FILE*pOpenStream);38. CStdioFileEx(LPCTSTRlpszFileName,UINTnOpenFlags);39. virtualCStdioFileEx();40. virtualBOOLOpen(LPCTSTRlpszFileName,UINTnOpenFlags,CFileException*pError=NULL);41. public:42. /文件类型值转换到字符串 43. CStringFileTypeToString();44. /获取文件类型 45. TextCodeGetFileType();46. /按行读取文件 47. BOOLReadString(CString&rString);48. /静态方法获取文件类型 49. staticTextCodeGetFileType(LPCTSTRlpszFileName);50. protected:51. TextCodem_FileType;/保存文件类型 52. conststaticintPREDEFINEDSIZE;/预定义一行文件所需空间 53. protected:54. /从UTF-8文件按行读取 55. BOOLReadStringFromUTF8File(CString&rString);56. /从ANSI文件按行读取 57. BOOLReadStringFromAnsiFile(CString&rString);58. /重UNCIDOE、UNICODEbigendian文件读取 59. BOOLReadStringFromUnicodeFile(CString&rString);60. /UTF-8字符串转换到UNICODE字符串 61. CStringUTF8ToUnicode(byte*szUTF8);62. /处理文件打开标志 63. UINTProcessFlags(LPCTSTRlpszFileName,UINT&nOpenFlags,TextCode&tc);64. ;65. 66. #endif/!defined(AFX_STDIOFILEEX_H_C1F1F96B_9417_4388_8D24_892EDFA2A616_INCLUDED_)cpp view plaincopyprint?1. /StdioFileEx.cpp:implementationoftheCStdioFileExclass. 2. / 3. / 4. 5. #includestdafx.h 6. #includeStdioFileEx.h 7. 8. #ifdef_DEBUG 9. #undefTHIS_FILE 10. staticcharTHIS_FILE=_FILE_;11. #definenewDEBUG_NEW 12. #endif 13. 14. / 15. /Construction/Destruction 16. / 17. /*static*/constintCStdioFileEx:PREDEFINEDSIZE=1024;18. CStdioFileEx:CStdioFileEx():CStdioFile()19. 20. m_FileType=ANSI;/指定默认类型 21. 22. CStdioFileEx:CStdioFileEx(FILE*pOpenStream):CStdioFile(pOpenStream)23. 24. CStringfilepath=pOpenStream-_tmpfname;/?尚不清楚File*结构 25. m_FileType=GetFileType(filepath);26. 27. CStdioFileEx:CStdioFileEx(LPCTSTRlpszFileName,UINTnOpenFlags):CStdioFile(lpszFileName,ProcessFlags(lpszFileName,nOpenFlags,m_FileType)28. 29. 30. CStdioFileEx:CStdioFileEx()31. 32. 33. 34. /- 35. /CStdioFileEx:GetFileType静态方法检测文本文件类型 36. /- 37. /*static*/TextCodeCStdioFileEx:GetFileType(LPCTSTRlpszFileName)38. 39. CFilefile;40. bytebuf3;/unsignedchar 41. TextCodetc;42. try43. 44. if(file.Open(lpszFileName,CFile:modeRead|CFile:shareDenyNone|CFile:typeBinary)45. 46. file.Read(buf,3);47. if(buf0=0xEF&buf1=0xBB&buf2=0xBF)48. tc=UTF8;49. else50. if(buf0=0xFF&buf1=0xFE)51. tc=UNICODE;52. else53. if(buf0=0xFE&buf1=0xFF)54. tc=UNICODEBIGENDIAN;55. else56. tc=ANSI;57. 58. else59. tc=FILEERROR;60. 61. catch(CFileExceptionex)62. 63. CStringerrormsg;64. errormsg.Format(_T(操作文件%s时发生异常!),ex.m_strFileName);65. AfxMessageBox(errormsg);66. 67. returntc;68. 69. /- 70. /CStdioFileEx:Readstring按行读取文本文件 71. /根据不同文件类型调用不同的读取函数 72. /- 73. BOOLCStdioFileEx:ReadString(CString&rString)74. 75. BOOLflag=FALSE;76. switch(m_FileType)77. 78. caseANSI:79. flag=ReadStringFromAnsiFile(rString);80. break;81. caseUNICODE:82. caseUNICODEBIGENDIAN:83. flag=ReadStringFromUnicodeFile(rString);84. break;85. caseUTF8:86. flag=ReadStringFromUTF8File(rString);87. break;88. caseFILEERROR:89. flag=FALSE;90. break;91. default:92. break;93. 94. returnflag;95. 96. /- 97. /CStdioFileEx:ReadstringFromAnsiFile从ANSI文件读取字符串 98. /- 99. BOOLCStdioFileEx:ReadStringFromAnsiFile(CString&rString)100. 101. BOOLflag;102. try103. 104. flag=CStdioFile:ReadString(rString);105. rString+=rn;106. 107. catch(CFileExceptionex)108. 109. CStringerrormsg;110. errormsg.Format(_T(操作文件%s时发生异常!),ex.m_strFileName);111. AfxMessageBox(errormsg);112. 113. returnflag;114. 115. /- 116. /CStdioFileEx:ReadstringFromUTF8File从UTF8文件中按行读取 117. /由于UTF-8编码多字节编码且各种字符长度不同,判断回车换行需要判断连续两个字节 118. /- 119. BOOLCStdioFileEx:ReadStringFromUTF8File(CString&rString)120. 121. longindex;122. bytecr=0x0d;/回车换行符 123. bytelf=0x0a;124. bytetemp2;125. bytetempbyte;126. byte*pbuf=newbytePREDEFINEDSIZE+1;127. memset(pbuf,0,(PREDEFINEDSIZE+1)*sizeof(byte);128. UINTreadlen;129. try130. 131. /跳过文件头移动文件指针 132. if(m_pStream&(GetPosition()=0)133. 134. CStdioFile:Seek(3*sizeof(byte),CFile:begin);135. 136. index=0;137. do138. 139. memset(temp,0,2*sizeof(byte);140. readlen=CFile:Read(temp,2);/CStdioFile:Read效果不同将省去回车符0x0d 141. if(!readlen)142. returnFALSE;143. /元素存贮到字节数组中 144. pbufindex+=temp0;145. pbufindex+=temp1;146. tempbyte=temp1;147. /判断回车换行 148. if(tempbyte=cr&temp0=lf)|(temp0=cr&temp1=lf)149. break;150. while(readlen=2&index8;198. low=wchtemp0&0x00FF;199. wchtemp0=(low8;201. low=wchtemp1&0x00FF;202. wchtemp1=(low8)|high;203. 204. wChLineindex+=wchtemp0;205. wChLineindex+=wchtemp1;206. /判断回车换行 207. if(wchtemp0=wchcr&wchtemp1=wchlf)208. break;209. 210. while(readlen=sizeof(wchar_t)*2)&indexPREDEFINEDSIZE);211. wChLineindex=0;212. CStringstrtext(wChLine,index);213. rString=strtext;214. if(rString.IsEmpty()215. flag=FALSE;216. 217. catch(CFileExceptionex)218. 219. CStringerrormsg;220. errormsg.Format(_T(操作文件%s时发生异常!),ex.m_strFileName);221. AfxMessageBox(errormsg);222. 223. deletewChLine;224. returnflag;225. 226. /- 227. /CStdioFileEx:UTF8ToUnicodeUTF-8字符串转换成UNICODE字符串 228. /- 229. CStringCStdioFileEx:UTF8ToUnicode(byte*szUTF8)230. 231. CStringstrret;232. strret=_T();233. if(!szUTF8)234. returnstrret;235. /获取转换后所需串空间的长度 236. intwcsLen=MultiByteToWideChar(CP_UTF8,0,(LPSTR)szUTF8,strlen(char*)szUTF8),NULL,0);237. LPWSTRlpw=newWCHARwcsLen+1;238. if(!lpw)239. returnstrret;240. memset(lpw,0,(wcsLen+1)*sizeof(wchar_t);241. /实施转换 242. MultiByteToWideChar(CP_UTF8,0,(LPSTR)szUTF8,243. strlen(char*)szUTF8),(LPWSTR)lpw,wcsLen);244. CStringstr(lpw);245. deletelpw;246. returnstr;247. 248. /- 249. /CStdioFileEx:GetFileType获取文件类型 250. /- 251. TextCodeCStdioFileEx:GetFileType()252. 253. returnm_FileType;254. 255. /- 256. /CStdioFileEx:FileTypeToString文件类型枚举值转换为字符串值 257. /- 258. CStringCStdioFileEx:FileTypeToString()259. 260. CStringstrtype;261. switch(m_FileType)262. 263. caseANSI:264. strtype.Format(%s,_T(ANSI);265. break;266. caseUTF8:267. strtype.Format(%s,_T(UTF8);268. break;269. caseUNICODE:270. strtype.Format(%s,_T(UNICODE);271. break;272. caseUNICODEBIGENDIAN:273. strtype.Format(%s,_T(UNICODEbigendian);274. break;275. caseFILEERROR:276. strtype.Format(%s,_T(FILEERROR);277. break;278. default:279. break;280. 281. returnstrtype;282. 283. /- 284. /CStdioFileEx:Open重载父类的文件打开操作改变不同类型文件的打开方式 285. /- 286. BOOLCStdioFileEx:Open(LPCTSTRlpszFileName,UINTnOpenFlags,CFileException*pError)287. 288. ProcessFlags(lpszFileName,nOpenFlags,m_FileType);/处理文件打开方式 289. returnCStdioFile:Open(lpszFileName,nOpenFlags,pError);290. 291. /- 292. /CStdioFileEx:ProcessFlags处理不同文件的打开方式 293. /ANSI文件采用文本读取,UNICODE、UNICDOEbigendian、UTF-8采用二进制方式读取 294. /- 295. UINTCStdioFileEx:ProcessFlags(LPCTSTRlpszFileName,UINT&nOpenFlags,TextCode&tc)296. 297. tc=CStdioFileEx:GetFileType(lpszFileName);298. if(nOpenFlags&CFile:modeReadWrite)|(nOpenFlags&CFile:modeRead)299. 300. switch(tc)301. 302. caseANSI:303. nOpenFlags|=CFile:typeText;304. nOpenFlags&=CFile:typeBinary;305. break;306. caseUTF8:307. nOpenFlags|=CFile:typeBinary;308. nOpenFlags&=CFile:typeText;309. break;310. caseUNICODE:311. nOpenFlags|=CFile:typeBinary;312. nOpenFlags&=CFile:typeText;313. break;314. caseUNICODEBIGENDIAN:315. nOpenFlags|=CFile:typeBinary;316. nOpenFlags&=CFile:typeText;317. break;318. caseFILEERROR:319. break;320. default:321. break;322. 323. 324. nOpenFlags|=CFile:shareDenyNone;325. returnnOpenFlags;326. 3.运行结果(1)测试部分核心代码/打开文件cpp view plaincopyprint?1. voidCReadStringDlg:OnBtnOpen()2. 3. /TODO:Addyourcontrolnotificationhandlercodehere 4. charszFilter=TextFiles(*.txt)|*.txt|AllFiles(*.*)|*.*|;5. CFileDialogfiledlg(TRUE,txt,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,this);6. if(IDOK=filedlg.DoModal()7. 8. m_strPath=filedlg.GetPathName();9. UpdateData(FALSE);10. m_ctrlEdit.SetSel(0,-1);11. m_ctrlEdit.Clear();12. if(m_stdiofileex.Open(m_strPath,CFile:modeRead)13. 14. m_strFileType=m_stdiofileex.FileTypeToString();15. UpdateData(FALSE);16. 17. else18. 19. MessageBox(_T(读取文件失败!);20. 21. 22. 23. /读取文件 24. voidCReadStringDlg:OnBtnRead()25. 26. /TODO:Addyourcontrolnotificationhandlercodehere

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论