本人能力、精力有限,所言所感都基於自身的實踐和有限的閱讀、查閱,如有錯誤,歡迎拍磚,敬請賜教——博客園:錢智慧。
總結:
CFile,其自身是不提供緩沖區的(?但CFile又有一個Flush,這一點目前我還沒弄明白),配合CArchive(CArchive類似一個緩沖區)為MFC的類提供序列化機制。文本的格式化輸出建議用ofstream或者CStdioFile(通過CString配合)。可以通過構造綁定文件,采用typeBinary模式,不能使用typeText模式。是MFC文件操作體系中的基類。其靜態成員函數(如GetStatus,配合CFileStatus)可以在不打開文件的情況下獲取文件的相關信息,如長度,通過CFileStatus的m_size),或者進行相關操作:如刪除、重命名。
CStdioFile,必須通過Open綁定文件,默認采用typeText模式,作為CFile子類,可以使用typeText,也可以使用typeBinary。
fstream是basic_fstream模板類的一個實例,關於文本和二進制,其默認模式是文本,可以通過指定ios::binary指明二進制模式,否則采取默認值。但要注意這是char版本的類。如果要技術Unicode,則需要用wfstream。如果通過fstream來獲取文件大小,只能通過指針偏移,這一點不如CFileStatus配合CFile::GetStatus來得簡便。
文本和二進制流:
區別在於讀寫時,對'\n'的解釋。見代碼:
1 // TODO: 在此添加控件通知處理程序代碼 2 char* str="It's length is 20\nab"; 3 CStdioFile f1; 4 CStdioFile f2; 5 f1.Open(TEXT("D:\\std_bin.txt"),CFile::modeCreate | CFile::modeWrite | CFile::typeBinary | CFile::shareDenyNone); 6 f1.Write(str,strlen(str)); 7 f1.Close(); 8 9 10 f2.Open(TEXT("D:\\std_text.txt"),CFile::modeCreate| CFile::modeWrite | CFile::typeText | CFile::shareDenyNone); 11 f2.Write(str,strlen(str)); 12 f2.Close();
運行后會發現std_text.txt比std_bin.txt大一個字節,因為typeText模式下,寫入字符串str時,會把\n擴展成\r\n寫入到文件中。以后你必須再以typeText模式去讀這個文件,\r\n才會再替換成\n。不然,會怎么樣呢:
1 //for循環執行前,std_text.txt在磁盤上,長度是21個字節 2 for (int i=0;i<100;++i) 3 { 4 //循環里的邏輯是:先將std_text.txt以typeBinary模式式讀進來,然后再 5 //用typeText模式寫出去 6 7 CStdioFile f; 8 f.Open(TEXT("D:\\std_text.txt"),CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone); 9 CFileStatus status; 10 f.GetStatus(TEXT("D:\\std_text.txt"),status); 11 //由於我們用於顯示,只是用緩沖區承載讀進來的文件內容,所以不考慮字符0 12 char* str=new char[status.m_size]; 13 f.Read(str,status.m_size); 14 f.Close(); 15 f.Open(TEXT("D:\\std_text.txt"),CFile::modeWrite | CFile::typeText | CFile::shareDenyNone); 16 f.Write(str,status.m_size); 17 f.Close(); 18 }
初始內容就是第一段代碼生成的,第二段代碼(上面的代碼)運行后,會發現std_text.txt在磁盤上的長度增加了100個字節。
所以,為了避免這種情況,最好遵循一個原則:以什么方式寫就以什么方式讀,這有點類似涉及到編碼的文件讀寫了。