作者purpose (purpose)
看板C_and_CPP
標題Re: [問題] BCB resource open pdf
時間Sat Apr 28 03:46:01 2012
※ 引述《leslieha (懂的付出才會幸福)》之銘言:
: 開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
: DBD 6.0
: 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
: 問題(Question):
: 把resource內的資料
: 直接開啟
: 而不用先存成檔案
: 程式碼(Code):(請善用置底文網頁, 記得排版)
: TResourceStream* res = new TResourceStream((int)HInstance,
: MY_MSG_FORMAT_289,
: "PDF");
: if(res == 0)
: {
: ShowMessage("TResourceStream fail");
: return;
: }
: else
: {
: res->SaveToFile("test.pdf");
: ShellExecute(NULL, "Open", "test.pdf" ,NULL,NULL,SW_MAXIMIZE);
: }
: 補充說明(Supplement):
: res->SaveToFile("test.pdf");
: 將resource內的資料存程test.pdf
: ShellExecute(NULL, "Open", "test.pdf" ,NULL,NULL,SW_MAXIMIZE);
: 將test.pdf開啟
: 目前程式如預期運作
: 但是會增加一個test.pdf中繼檔
: 考量到以後會有很多資料包到resource內
: 若以後皆用此方法,會產生很多個 pdf
: 若執行檔是被燒到CD-ROM上
: 此方法應該行不通
: 請問
: 是否有辦法連test.pdf中繼檔都不用產生
: 即可用pdf reader開起pdf檔?
http://www.eterlogic.com/help/vdsdk/CppPage2_5.html
http://www.eterlogic.com/help/vdsdk/index.html
Virtual Drive SDK (商業軟體),可以動態建立、刪除磁碟槽,比如 Z:
之後的讀寫可以轉到指定的記憶體位址。
沒試過,不知道還能不能進一步產生 Z:\test.pdf 供 pdf reader 讀取。
如果這個不能就找其他商業的 Ram Disk 相關軟體吧,
在 Windows 應該是沒有內建的解決方案。
Linux 好像有個 tmpfs 我也沒試過,不知道具體效果,反正你也不用 Linux。
Wikipedia 是寫說 Windows 可以用 FILE_ATTRIBUTE_TEMPORARY + CreateFile() 代替
tmpfs,這我測過。
新增一個 tmp.txt 再把硬碟上的 menu.lst 檔案內容寫入
進去,先不關檔案,用其他程式開啟 tmp.txt,結果無法開啟檔案,程式碼如下:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
int main() {
HANDLE hFile = ::CreateFileA("tmp.txt", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE |
FILE_SHARE_DELETE, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY |
FILE_FLAG_DELETE_ON_CLOSE, NULL);
HANDLE hSrcFile = ::CreateFileA("D:\\Desktop\\menu.lst", GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwBytesRead, dwBytesWritten, dwPos;
BYTE buff[4096];
while (ReadFile(hSrcFile, buff, sizeof(buff), &dwBytesRead, NULL) &&
dwBytesRead > 0) {
dwPos = SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile(hFile, buff, dwBytesRead, &dwBytesWritten, NULL);
}
CloseHandle(hSrcFile);
puts("Wait for another process");
_getch();
CloseHandle(hFile);
return 0;
}
參考資料:
http://msdn.microsoft.com/en-us/library/aa363858.aspx#caching_behavior
http://blogs.msdn.com/b/larryosterman/archive/2004/04/19/116084.aspx
把 FILE_FLAG_DELETE_ON_CLOSE 拿掉就能開啟,但開啟後又不知道怎麼確定
是真的從記憶體讀取,中間沒牽涉到硬碟,所以算了。
感覺你只是要避免產生檔案這件事而已,那其實最好的方法是用 Shared Memory,
也就是你的程式在記憶體裡面放 pdf 資料,另外的程式也到這個共享的記憶體去讀取,
但是這方法要程式二主動呼叫 OpenFileMapping 才行,你干涉不了的,
除非兩邊的程式都你在維護才適用。
Creating Named Shared Memory:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551.aspx
一般狀況應該是像 PTT 這種伺服器,可能一萬個人傳資料過來,每份都必須存成
一個檔案 A0~A9999,但檔案每個都不大,又很少會被讀取,也許幾個小時內,只有
幾份 Ax 有被人拿去用,這種情況下,檔案不必急著寫入,可以推遲,
這可能才是前面 FILE_ATTRIBUTE_TEMPORARY 的主要目的吧?
每個作業系統都會有一大份主記憶體用來對硬碟檔案快取,應該是透過 OS 的
cache manager 去處理,反正只要快取記憶體還夠用,就不寫入這些檔案到硬碟去,
晚點再存。另外如果你的 PDF 一開始是從硬碟單獨讀取上來的檔案,那大可有機會
被快取到記憶體,第二個程式開同樣檔案時,也未必要再讀一次硬碟,只是你堅持要
把 PDF 塞到 resource 裡,那 cache manager 來說,大概是很難快取吧。
我想商業上如果卡在大量的硬碟讀寫,要嘛是研究 Windows 的快取機制,看怎樣用內建
的工具跑出最高效率,要嘛就真的是用 RAMDISK,一開始就用主記憶體模擬硬碟,就像
最前面提的 Virtual Drive SDK 那樣。
沒經驗純粹猜測而已,附帶一提的是,之前喵到 Windows Internal 這書對快取機制
有蠻多探討,有需要的人可以找這管道。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 124.8.137.112
※ 編輯: purpose 來自: 124.8.137.112 (04/28 03:46)
推 EdisonX:想請教p大,RamDisk技術,是否即是將ram 當 disk使用?那記憶 04/30 09:49
→ EdisonX:體不夠切的話是否就是allocate fail?細思這行為似乎和 04/30 09:49
→ EdisonX:MemoryMappedFile 機制相仿? 04/30 09:50
推 EdisonX:我於文中找到答案了,請略過上述敘述,謝謝分享 ^^ 04/30 10:04