CStdioFile類

參數內容:

第一個參數爲路徑+文件名,最後一個爲錯誤出現的結構.

現在解釋下第二個參數

CFile::modeCreate   Directs the constructor to create a new file. If the file exists already, it is truncated to 0 length.

指定構造器創建一個新的文件,如果文件已經存在,則內容截0.

CFile::modeNoTruncate   Combine this value with modeCreate. If the file being created already exists, it is not truncated to 0 length. Thus the file is guaranteed to open, either as a newly created file or as an existing file. This might be useful, for example, when opening a settings file that may or may not exist already. This option applies to CStdioFile as well.

modeNoTruncate

假如你不用這個參數的話,用modeCreate模式創建和打開一個文件,假如這個文件已經存在,則會清空這個已經存在的文件,加上modeNoTruncate的話,就不會清空這個文件了

CFile::modeRead   Opens the file for reading only.

只是以讀取方式打開

CFile::modeReadWrite   Opens the file for reading and writing.

讀與寫同時

CFile::modeWrite   Opens the file for writing only.
只寫

CFile::modeNoInherit   Prevents the file from being inherited by child processes.

阻止這個文件被子進程繼承

CFile::shareDenyNone   Opens the file without denying other processes read or write access to the file.Create fails if the file has been opened in compatibility mode by any other process.

打開這個文件同時允許其它進程讀寫這個文件。如果文件被其它進程以incompatibility模式打開,這是create操作會失敗。

CFile::shareDenyRead   Opens the file and denies other processes read access to the file. Create fails if the file has been opened in compatibility mode or for read access by any other process.

打開文件拒絕其它任何進程讀這個文件。如果文件被其它進程用compatibility模式或者是讀方式打開,create操作失敗。

CFile::shareDenyWrite   Opens the file and denies other processes write access to the file. Create fails if the file has been opened in compatibility mode or for write access by any other process.

打開文件拒絕其它任何進程寫這個文件。如果文件被其它進程用compatibility模式或者是寫方式打開,create操作失敗。

CFile::shareExclusive   Opens the file with exclusive mode, denying other processes both read and write access to the file. Construction fails if the file has been opened in any other mode for read or write access, even by the current process.

 以獨佔方式打開這個文件,不允許其它進程讀寫這個文件。

CFile::shareCompat   This flag is not available in 32 bit MFC. This flag maps to CFile::shareExclusivewhen used in CFile::Open.

這個標誌在32位的MFC中無效。

CFile::typeText   Sets text mode with special processing for carriage return–linefeed pairs (used in derived classes only).

CFile::typeText   設置成對回車換行對有特殊處理的文本模式(僅用在派生類中) 
CFile::typeBinary   設置二進制模式(僅用在派生類中)

 

 

 

 

CStdioFile繼承自CFile,一個CStdioFile 對象代表一個用運行時函數fopen 打開的C 運行時流文件。

      流式文件是被緩衝的,而且可以以文本方式(缺省)或二進制方式打開。文本方式提供對硬回車—換行符對的特殊處理。當你將一個換行符(0x0A)寫入一個文本方式的CStdioFile 對象時,字節對(0x0D,0x0A)被髮送給該文件。當你讀一個文件時,字節對(0x0D,0x0A)被翻譯爲一個字節(0x0A)。 
  CStdioFile 不支持Duplicate,LockRange,和UnlockRange 這幾個CFile 函數。如果在CStdioFile 中調用了這幾個函數,將會出現CNoSupported 異常。 
  CStdioFile::ReadString(LPTSTR lpsz, UINT nMax); 
  讀取一行文本到緩衝區,遇到“0x0D,0x0A”時停止讀取,並且去掉硬回車“0x0D”,保留換行符“0x0A”,在字符串末尾添加“/0”(0x00)。nMax個字符裏包含0x00這個字符。分析如下: 
  1)如果nMax <= 字符數,讀取(nMax-1)個字符 + 0x00 
  2)如果nMax = 字符數 + 1,讀取nMax個字符 + 0x00 
  3)如果nMax > 字符數,讀取nMax個字符 + 0x0A + 0x00 
  CStdioFile::ReadString(CString &rString);(重載) 
  讀取一行文本到rString,遇到回車換行符停止讀取。回車和換行符不讀到rString,而且末尾也沒有添加“/0”。 
  CStdioFile::WriteString( LPCTSTR lpsz );(不支持CString直接寫入) 
  將一個緩衝區中的數據寫入與CStdioFile 對象關聯的文件中。結束的空字符(“/0”)不被寫入該文件。lpsz 中的所有換行符都被以一個硬回車換行符對寫入該文件,即“/n”被轉化成“/r/n”寫入到文件裏。 
  CFile的派生類CStdioFile提供了對文件進行流式的操作功能。其中函數void CStdioFile::WriteString( LPCTSTR lpsz )寫入一個字符串,需要給字符串lpsz的末尾加上換行標誌”/r/n”;函數bool CStdioFile::ReadString(CString &rString )從文件中讀取一行,如果文件未讀完返回true,否則返回false。   
    
    當CStdioFile.WriteString無法處理中文時,把工程的字符集屬性 改成 使用多字節字符集 就可以了,具體設置方法如:打開項目屬性-->配置屬性-->常規-->字符集-->改成 使用多字節字符集
    要注意的是CStdioFile在_MSBC環境下讀取任何ANSI文本數據都沒問題,在UNICODE環境下讀取ANSI文本中的中文時就會顯示亂碼。其原因是由於CStdioFile 讀取ANSI文本數據時按char類型讀取,在_MSBC下可以直接填充到CString,在UNICODE環境下要先將char轉換成寬字符 WCHAR,然後再填充到CString,即一個漢字的兩個char將變成兩個UNICODE字符WCHAR。那麼問題如何解決呢?實際上在UNICODE環境下,file.ReadString(strLine)取得的數據是char類型,但是存儲在UNICODE字符串中。爲了取得真實數據,必須對strLine進行處理。

  在CFile類中提供了2種模式,typeBinary和typeText。如果是CTextFile類的話當然要強制使用typeText類型了。那麼CStdioFile是怎麼做的呢?
  BOOL CStdioFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pException) 
  {
   …
   /// 調用基類打開文件,注意通過nOpenFlags & ~typeText過濾了文件的文本屬性
   if (!CFile::Open(lpszFileName, (nOpenFlags & ~typeText), pException))
   return FALSE;
   …
  ///轉換找開模式
  if (nOpenFlags & typeBinary)
   szMode[nMode++] = 'b', nFlags ^= _O_TEXT;
   else
   szMode[nMode++] = 't';
   …
   // open a C-runtime low-level file handle
   int nHandle = _open_osfhandle((UINT_PTR) m_hFile, nFlags);
   // open a C-runtime stream from that handle
   if (nHandle != -1)
   m_pStream = _fdopen(nHandle, szMode);
   …
  }
   由上面的代碼可以看出,CStdioFile強制過濾了typeText標誌,使得文件打開模式可以是二進制模式。這已經可以證明CStdioFile不是一個純粹TextFile類。
   再仔細看上面的代碼,在調用基類打開後,又使用_open_osfhandle和_fdopen做了奇怪的轉換,察看m_pStream的類型 
   FILE* m_pStream; // stdio FILE
   這是一個標準I/O的FILE結構。如果再進一步的研究CStdioFile的源碼,還會發現它都是調用標準I/O的函數來操作的,比如用_fputts/_fgetts來實現WriteString/ReadString,用fread/fwrite/fseek來替代Read/Write/Seek。注意CStdioFile並沒有使用CFile的Read/Write/Seek函數,如果在Open裏將使用fopen直接打開的話,CStdioFile甚至可以說和CFile沒有任何的關係。,由此這個類叫做CStdioFile就不奇怪了。
   爲什麼要研究這個問題呢?前一段在csdn.net上看到不少人問爲什麼UNICODE的文本文件處理出現亂碼?他們很驚異發現平常作爲TextFile的處理類用得CStdioFile竟然失效了。真的是它失效了嗎?其實是標準的I/O操作並不支持UNICODE的模式而已。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章