標籤:
轉自:http://blog.csdn.net/cashey1991/article/details/6769038
@1.問題描述:
C和C++的初學者經常採用一行一行讀入檔案的辦法對檔案資料進行處理。但是經常會有一些情況需要將一個檔案整體一次讀入記憶體處理。而C和C++庫中並沒有提供直接一次讀入檔案全部資料的函數。
@2.解決方案:
目前給出C和C++的解決方案,下面兩個程式只是用於示範,不過這些代碼已經很容易改寫成想要的函數了。
解決這個問題的思路是:
1.由於要將檔案完整讀入,所以必須使用二進位方式開啟(若文本方式開啟,檔案流中會把一些非字元的資料過濾掉,我們將讀取不到那些內容)。
2.開啟檔案後,我們首先擷取檔案的大小,然後在記憶體中分配足夠的空間,再把檔案拷貝到記憶體空間中。之後使用記憶體空間進行資料處理,示範程式中沒有真正的處理,我們只是簡單將其輸出。
@3.代碼:
C實現
#include <stdio.h>
#include <stdlib.h>
int main ()
{
FILE * pFile;
long lSize;
char * buffer;
size_t result;
/* 若要一個byte不漏地讀入整個檔案,只能採用二進位方式開啟 */
pFile = fopen ("test.txt", "rb" );
if (pFile==NULL)
{
fputs ("File error",stderr);
exit (1);
}
/* 擷取檔案大小 */
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
/* 分配記憶體儲存整個檔案 */
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL)
{
fputs ("Memory error",stderr);
exit (2);
}
/* 將檔案拷貝到buffer中 */
result = fread (buffer,1,lSize,pFile);
if (result != lSize)
{
fputs ("Reading error",stderr);
exit (3);
}
/* 現在整個檔案已經在buffer中,可由標準輸出列印內容 */
printf("%s", buffer);
/* 結束示範,關閉檔案並釋放記憶體 */
fclose (pFile);
free (buffer);
return 0;
}
C++實現
#include <iostream>
#include <fstream>
using namespace std;
int main () {
filebuf *pbuf;
ifstream filestr;
long size;
char * buffer;
// 要讀入整個檔案,必須採用二進位開啟
filestr.open ("test.txt", ios::binary);
// 擷取filestr對應buffer對象的指標
pbuf=filestr.rdbuf();
// 調用buffer對象方法擷取檔案大小
size=pbuf->pubseekoff (0,ios::end,ios::in);
pbuf->pubseekpos (0,ios::in);
// 分配記憶體空間
buffer=new char[size];
// 擷取檔案內容
pbuf->sgetn (buffer,size);
filestr.close();
// 輸出到標準輸出
cout.write (buffer,size);
delete []buffer;
return 0;
}
@4.注意的問題:
在這個示範程式中,如果採用文本方式開啟會如何呢?即把C實現中的檔案開啟改為pFile = fopen ("test.txt","r" ),C++中的檔案開啟改為filestr.open ("test.txt")
雖然這個用於測試的檔案本身是一個文字檔,常值內容為:
test.txt
[plain] view plaincopy
- abcdefghijklm
-
- abcdefghijklm
-
- ppdsbd
但是如果採用文字模式開啟仍會出現問題,測試中的“C實現”代碼的程式會輸出:
[cpp] view plaincopy
- Reading error
原因是有一些字元被檔案流處理掉了,這造成fread函數講到的字元數少於檔案大小lSize,傳回值result不等於lSize於是程式輸出Reading error後退出了。
同樣的情況在C++實現的代碼中也有,但是C++程式並沒有退出,但它的輸出結果不對,內容如下(僅為本機測試結果,因時因機器而異)
[plain] view plaincopy
- abcdefghijklm
-
- abcdefghijklm
-
- ppdsbdes\M
很明顯末尾多出了"es\M"四個無效字元,很明顯檔案的末尾的字串終止符(‘\0‘)被處理掉了,它並沒有被寫入buffer中,以致輸出時多輸出了四個無效字元。
C、C++一次將整個檔案讀入記憶體