CFile 若有下 modeCreate 的屬性時,會產生一個全新的空檔案,若是希望 CFile 在檔案存在的情況下使用 Open 舊檔案不產生新檔,必須再加上 CFile::modeNoTruncate 屬性。
fileLog.Open(strFullFilePath, File::modeReadWrite|CFile::modeNoTruncate|CFile::modeCreate)
若 ThreadA 在寫入檔案的同時,要讓 ThreadB 讀取,通常用於解碼時,A 由前往後解,解到某個比例就通知 B 使用,常發生在下載 pdf、ppt 投影片檔或影片預覽等狀況,這時要用 shareDenyWrite 和 shareDenyRead,例如
int main()
{
::BeginThread(ThreadA);
return TRUE;
}
UINT ThreadA()
{
BOOL bFinish = FALSE;
CFile file;
file.Open(_T("Temp.xml"),
CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite);
while(!bFinish)
{
file.write();
if(/*下載了了5%或300KB之類的*/)
{
::BeginThread(ThreadB);
}
bFinish = /*下載完沒*/;
}
return TRUE;
}
UINT ThreadB()
{
CFile file;
file.Open(_T("Temp.xml"), CFile::modeRead|CFile::shareDenyRead);
while(file.Read(btBuf, 1024))
{
}
return TRUE;
}
若要讓執行緒 A 與執行緒 B 同時讀一個檔案,則是兩處 Open 都要加上 shareDenyNone,理由很直觀,因為 ThreadA 讀時要允許 ThreadB 也可以讀,ThreadB 在讀時,ThreadA 又不一定已經讀完關閉了,所以也要允許別人可以讀,例如
int main()
{
::BeginThread(ThreadA);
::BeginThread(ThreadB);
return TRUE;
}
UINT ThreadA()
{
CFile file;
file.Open(_T("Temp.xml"), CFile::modeRead|CFile::shareDenyNone);
while(file.Read(btBuf, 1024))
{
}
return TRUE;
}
UINT ThreadB()
{
CFile file;
file.Open(_T("Temp.xml"), CFile::modeRead|CFile::shareDenyNone);
while(file.Read(btBuf, 1024))
{
}
return TRUE;
}
有時在記憶體不能亂用的平台上,像手機或 Pad 等硬體,例如 Windows mobile 每一個 Application 只能使用 32MB 的主記憶體,這種情況就比較麻煩,尤其產生的是無法由檔頭得知容量的檔案類型,如 mp3 是由一個一個 frame 組成的,以取樣率 128Kbits 的 mp3 檔來看,意即每個 frame 為 16KBytes (一秒),再由多少個 frame 計算出整首歌的總時間,好死不死我們的 mp3 要從網路上下載下來,不可能等到下載完才播,所以我們要產生一個空的 mp3 讓其他行程知道這個 mp3 的總長度,但又不能一次 new 出 5MB 的空間塞給 CFile,這很可能會爆記憶體,這時可以使用一次 100KBytes 的方式塞入檔案,
int main()
{
DWORD dwWrote = 0;
ULONGLONG ullSize = file.GetLength(); // 例如 5MB
DWORD dwMaxBytes = (DWORD)ullSize - 1;
do {
if(dwMaxBytes - dwWrote >= 102400) // 100KBytes
{
BYTE bt[10240] = {0};
fileMP3.Write(bt, 10240);
dwWrote += 10240;
}
else
{
int nLastBytes = dwMaxBytes - dwWrote;
BYTE* bt = new BYTE[nLastBytes];
::ZeroMemory(bt, nLastBytes);
fileMP3.Write(bt, nLastBytes);
dwWrote = (DWORD)ullSize;
delete [] bt;
}
} while(dwWrote < ullSize);
fileMP3.SeekToBegin(); // 記得把檔案指標移到檔頭以免等等從尾巴開始寫
return TRUE;
}
如此就可以用比較不會爆記憶體的方式產生一個空的檔案。
沒有留言:
張貼留言