青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ Coder

HCP高性能計算架構,實現,編譯器指令優化,算法優化, LLVM CLANG OpenCL CUDA OpenACC C++AMP OpenMP MPI

C++博客 首頁 新隨筆 聯系 聚合 管理
  98 Posts :: 0 Stories :: 0 Comments :: 0 Trackbacks

本文摘自:http://blog.vckbase.com/teacheryang/archive/2005/06/27/8883.html

一、前言
  公元一九九五年某個夜黑風高的晚上,我的一位老師跟我說:“小楊呀,以后寫程序就和搭積木一樣啦。你趕快學習一些OLE的技術吧......”,當時我心里就尋思 :“開什么玩笑?搭積木方式寫程序?再過100年吧......”,但作為一名聽話的好學生,我開始在書店里“踅摸”(注1)有關OLE的書籍(注2)。功夫不負有心人,終于買到了我的第一本COM書《OLE2 高級編程技術》,這本800多頁的大布頭花費了我1/5的月工資呀......于是開始日夜耕讀.....
功夫不負有心人,我堅持讀完了全部著作,感想是:這本書,在說什么吶?
功夫不負有心人,我又讀完了一遍大布頭,感想是:咳~~~,沒懂!
功夫不負有心人,我再,我再,我再讀 ... 感想是:哦~~~,讀懂了一點點啦,哈哈哈。
...... ......
功夫不負有心人,我終于,我終于懂了。
800頁的書對現在的我來說,其實也就10幾頁有用。到這時候才體會出什么叫“書越讀越薄”的道理了。到后來,能買到的書也多了,上網也更方便更便宜了......
  為了讓VCKBASE上的朋友,不再經歷我曾經的痛苦、不再重蹈我“無頭蒼蠅”般探索的艱辛、為了VCKBASE的蓬勃發展、為了中國軟件事業的騰飛(糟糕,吹的太也高了)......我打算節約一些在 BBS 上賺分的時間,寫個系列論文,就叫“COM組件設計與應用”吧。今天是第一部分——起源。

二、文件的存儲
  傳說350年前,牛頓被蘋果砸到了頭,于是發現了萬有引力。但到了二十一世紀的現在,任何一個技術的發明和發展,已經不再依靠圣人靈光的一閃。技術的進步轉而是被社會的需求、商業的利益、競爭的壓力、行業的滲透等推動的。微軟在Windows平臺上的組件技術也不例外,它的發明,有其必然因素。什么是這個因素那?答案是——文件的存儲。
  打開記事本程序,輸入了一篇文章后,保存。——這樣的文件叫“非結構化文件”;
  打開電子表格程序,輸入一個班的學生姓名和考試成績,保存。——這樣的文件叫“標準結構化文件”;
  在我們寫的程序中,需要把特定的數據按照一定的結構和順序寫到文件中保存。——這樣的文件叫“自定義結構化文件”;(比如 *.bmp 文件)
  以上三種類型的文件,大家都見的多了。那么文件存儲就依靠上述的方式能滿足所有的應用需求嗎?恩~~~,至少從計算機發明后的50多年來,一直是夠用的了。嘿嘿,下面看看商業利益的推動作用,對文件 的存儲形式產生了什么變化吧。30歲以上的朋友,我估計以前都使用過以下幾個著名的軟件:WordStar(獨霸DOS下的英文編輯軟件),WPS(裘伯君寫的中文編輯軟件,據說當年的市場占有率高達90%,各種計算機培訓班的必修課程),LOTUS-123(蓮花公司出品的電子表格軟件)......
微軟在成功地推出 Windows 3.1 后,開始垂涎桌面辦公自動化軟件領域。微軟的 OFFICE 開發部門,各小組分別獨立地開發了 WORD 和 EXCEL 等軟件,并采用“自定義結構”方式,對文件進行存儲。在激烈的市場競爭下,為了打敗競爭對手,微軟自然地產生了一個念頭------如果我能在 WORD 程序中嵌入 EXCEL,那么用戶在購買了我 WORD 軟件的情況下,不就沒有必要再買 LOTUS-123 了嗎?!“惡毒”(中國微軟的同志們看到了這個詞,不要激動,我是加了引號的呀)的計劃產生后,他們開始了實施工作,這就是 COM 的前身 OLE 的起源(注3)。但立刻就遇到了一個嚴重的技術問題:需要把 WORD 產生的 DOC 文件和 EXCEL 產生的 XLS 文件保存在一起。

方案

優點

缺點

建立一個子目錄,把 DOC、XLS 存儲在這同一個子目錄中。 數據隔離性好,WORD 不用了解 EXCEL 的存儲結構;容易擴展。 結構太松散,容易造成數據的損壞或丟失。
不易攜帶。
修改文件存儲結構,在DOC結構基礎上擴展出包容 XLS 的結構。 結構緊密,容易攜帶和統一管理。 WORD 的開發人員需要通曉 EXCEL 的存儲格式;缺少擴展性,總不能新加一個類型就擴展一下結構吧?!

  以上兩個方案,都有嚴重的缺陷,怎么解決那?如果能有一個新方案,能夠合并前兩個方案的優點,消滅缺點,該多好呀......微軟是作磁盤操作系統起家的,于是很自然地他們提出了一個非常完美的設計方案,那就是把磁盤文件的管理方式移植到文件中了------復合文件,俗稱“文件中的文件系統”。連微軟當年都沒有想到,就這么一個簡單的想法,居然最后就演變出了 COM 組件程序設計的方法。可以說,復合文件是 COM 的基石。下圖是磁盤文件組織方式與復合文件組織方式的類比圖:


圖一、左側表示一個磁盤下的文件組織方式,右側表示一個復合文件內部的數據組織方式。

三、復合文件的特點
  1、
復合文件的內部是使用指針構造的一棵樹進行管理的。編寫程序的時候要注意,由于使用的是單向指針,因此當做定位操作的時候,向后定位比向前定位要快;
  2、
復合文件中的“流對象”,是真正保存數據的空間。它的存儲單位為512字節。也就是說,即使你在流中只保存了一個字節的數據,它也要占據512字節的文件空間。啊~~~,這也太浪費了呀?不浪費!因為文件保存在磁盤上,即使一個字節也還要占用一個“簇”的空間那;
  3、
不同的進程,或同一個進程的不同線程可以同時訪問一個復合文件的不同部分而互不干擾;
  4、
大家都有這樣的體會,當需要往一個文件中插入一個字節的話,需要對整個文件進行操作,非常煩瑣并且效率低下。而復合文件則提供了非常方便的“增量訪問”能力;
  5、當頻繁地刪除文件,復制文件后,磁盤空間會變的很零碎,需要使用磁盤整理工具進行重新整合。和磁盤管理非常相似,復合文件也會產生這個問題,在適當的時候也需要整理,但比較簡單,只要調用一個函數就可以完成了。

四、瀏覽復合文件
  VC6.0 附帶了一個工具軟件“復合文件瀏覽器”,文件名是“vc目錄\Common\Tools\DFView.exe”。為了方便使用該程序,可以把它加到工具(tools)菜單中。方法是:Tools\Customize...\Tools卡片中增加新的項目。運行 DFView.exe,就可以打開一個復合文件進行觀察了(注4)。但奇怪的是,在 Microsoft Visual Studio .NET 2003 中,我反而找不到這個工具程序了,汗!不過這恰好提供給大家一個練習的機會,在你閱讀完本篇文章并掌握了編程方法后,自己寫一個“復合文件瀏覽編輯器”程序,又練手了,還有實用的價值。

五、復合文件函數
  復合文件的函數和磁盤目錄文件的操作非常類似。所有這些函數,被分為3種類型:WIN API 全局函數,存儲 IStorage 接口函數,流 IStream 接口函數。什么是接口?什么是接口函數?以后的文章中再陸續介紹,這里大家只要把“接口”看成是完成一組相關操作功能的函數集合就可以了。

WIN API 函數

功能說明

StgCreateDocfile() 建立一個復合文件,得到根存儲對象
StgOpenStorage() 打開一個復合文件,得到根存儲對象
StgIsStorageFile() 判斷一個文件是否是復合文件

 

IStorage 函數

功能說明

CreateStorage() 在當前存儲中建立新存儲,得到子存儲對象
CreateStream() 在當前存儲中建立新流,得到流對象
OpenStorage() 打開子存儲,得到子存儲對象
OpenStream() 打開流,得到流對象
CopyTo() 復制存儲下的所有對象到目標存儲中,該函數可以實現“整理文件,釋放碎片空間”的功能
MoveElementTo() 移動對象到目標存儲中
DestoryElement() 刪除對象
RenameElement() 重命名對象
EnumElements() 枚舉當前存儲中所有的對象
SetElementTimes() 修改對象的時間
SetClass() 在當前存儲中建立一個特殊的流對象,用來保存CLSID(注5)
Stat() 取得當前存儲中的系統信息
Release() 關閉存儲對象
 

IStream 函數

功能說明

Read() 從流中讀取數據
Write() 向流中寫入數據
Seek() 定位讀寫位置
SetSize() 設置流尺寸。如果預先知道大小,那么先調用這個函數,可以提高性能
CopyTo() 復制流數據到另一個流對象中
Stat() 取得當前流中的系統信息
Clone() 克隆一個流對象,方便程序中的不同模塊操作同一個流對象
Release() 關閉流對象
 
WIN API 補充函數 功能說明
WriteClassStg() 寫CLSID到存儲中,同IStorage::SetClass()
ReadClassStg() 讀出WriteClassStg()寫入的CLSID,相當于簡化調用IStorage::Stat()
WriteClassStm() 寫CLSID到流的開始位置
ReadClassStm() 讀出WriteClassStm()寫入的CLSID
WriteFmtUserTypeStg() 寫入用戶指定的剪貼板格式和名稱到存儲中
ReadFmtUserTypeStg() 讀出WriteFmtUserTypeStg()寫入的信息。方便應用程序快速判斷是否是它需要的格式數據。
CreateStreamOnHGlobal() 內存句柄 HGLOBAL 轉換為流對象
GetHGlobalFromStream() 取得CreateStreamOnHGlobal()調用中使用的內存句柄

  為了讓大家快速地瀏覽和掌握基本方法,上面所列表的函數并不是全部,我省略了“事務”函數和未實現函數部分。更全面的介紹,請閱讀 MSDN。
下面程序片段,演示了一些基本函數功能和調用方法。
示例一:建立一個復合文件,并在其下建立一個子存儲,在該子存儲中再建立一個流,寫入數據。

  1. void SampleCreateDoc()  
  2. {  
  3.   ::CoInitialize(NULL);   // COM 初始化  
  4.                // 如果是MFC程序,可以使用AfxOleInit()替代  
  5.   HRESULT hr;   // 函數執行返回值  
  6.   IStorage *pStg = NULL; // 根存儲接口指針  
  7.   IStorage *pSub = NULL; // 子存儲接口指針  
  8.   IStream *pStm = NULL; // 流接口指針  
  9.   
  10.   hr = ::StgCreateDocfile(  // 建立復合文件  
  11.         L"c:\\a.stg"// 文件名稱  
  12.         STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, // 打開方式  
  13.         0, // 保留參數  
  14.         &pStg); // 取得根存儲接口指針  
  15.   ASSERT( SUCCEEDED(hr) ); // 為了突出重點,簡化程序結構,所以使用了斷言。  
  16.                  // 在實際的程序中則要使用條件判斷和異常處理  
  17.   
  18.   hr = pStg->CreateStorage( // 建立子存儲  
  19.         L"SubStg"// 子存儲名稱  
  20.         STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,  
  21.         0,0,  
  22.         &pSub); // 取得子存儲接口指針  
  23.   ASSERT( SUCCEEDED(hr) );  
  24.   
  25.   hr = pSub->CreateStream(  // 建立流  
  26.         L"Stm"// 流名稱  
  27.         STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,  
  28.         0,0,  
  29.         &pStm); // 取得流接口指針  
  30.   ASSERT( SUCCEEDED(hr) );  
  31.   
  32.   hr = pStm->Write( // 向流中寫入數據  
  33.         "Hello"// 數據地址  
  34.         5, // 字節長度(注意,沒有寫入字符串結尾的\0)  
  35.         NULL); // 不需要得到實際寫入的字節長度  
  36.   ASSERT( SUCCEEDED(hr) );  
  37.   
  38.   if( pStm ) pStm->Release(); // 釋放流指針  
  39.   if( pSub ) pSub->Release(); // 釋放子存儲指針  
  40.   if( pStg ) pStg->Release(); // 釋放根存儲指針  
  41.   
  42.   ::CoUninitialize() // COM 釋放  
  43.            // 如果使用 AfxOleInit(),則不調用該函數  
  44. }  

 


圖二、運行示例程序一后,使用 DFView.exe 打開觀察復合文件的效果圖

示例二:打開一個復合文件,枚舉其根存儲下的所有對象。

  1. #include // ANSI、MBCS、UNICODE 轉換  
  2. void SampleEnum()   
  3. {   
  4.   // 假設你已經做過 COM 初始化了  
  5.   LPCTSTR lpFileName = _T( "c:\\a.stg" );  
  6.   HRESULT hr;  
  7.   IStorage *pStg = NULL;  
  8.   
  9.   USES_CONVERSION; // (注6)  
  10.   LPCOLESTR lpwFileName = T2COLE( lpFileName ); // 轉換T類型為寬字符  
  11.   hr = ::StgIsStorageFile( lpwFileName ); // 是復合文件嗎?  
  12.   if( FAILED(hr) )  
  13.     return;  
  14.   hr = ::StgOpenStorage( // 打開復合文件  
  15.         lpwFileName, // 文件名稱  
  16.         NULL,  
  17.         STGM_READ | STGM_SHARE_DENY_WRITE,  
  18.         0,  
  19.         0,  
  20.         &pStg); // 得到根存儲接口指針  
  21.   IEnumSTATSTG *pEnum=NULL; // 枚舉器  
  22.   hr = pStg->EnumElements( 0, NULL, 0, &pEnum );  
  23.   ASSERT( SUCCEEDED(hr) );  
  24.   STATSTG statstg;  
  25.   while( NOERROR == pEnum->Next( 1, &statstg, NULL) )  
  26.   {  
  27.     // statstg.type 保存著對象類型 STGTY_STREAM 或 STGTY_STORAGE  
  28.     // statstg.pwcsName 保存著對象名稱  
  29.     // ...... 還有時間,長度等很多信息。請查看 MSDN  
  30.     ::CoTaskMemFree( statstg.pwcsName ); // 釋放名稱所使用的內存(注6)  
  31.   }  
  32.   
  33.   if( pEnum ) pEnum->Release();  
  34.   if( pStg ) pStg->Release();  
  35. }  

 

六、小結
  復合文件,結構化存儲,是微軟組件思想的起源,在此基礎上繼續發展出了持續性、命名、ActiveX、對象嵌入、現場激活......一系列的新技術、新概念。因此理解和掌握 復合文件是非常重要的,即使在你的程序中并沒有全面使用組件技術,復合文件技術也是可以單獨被應用的。祝大家學習快樂,為社會主義軟件事業而奮斗:-)

留作業啦......
作業1:寫個小應用程序,從 MSWORD 的 doc 文件中,提取出附加信息(作者、公司......)。
作業2:寫個全功能的“復合文件瀏覽編輯器”。

注1:踅摸(xuemo),動詞,北方方言,尋找搜索的意思。
注2:問:為什么不上網查資料學習?
答:開什么國際玩笑!在那遙遠的1995年代,我的500塊工資,不吃不喝正好夠上100小時的Internet網。
注3:OLE,對象的連接與嵌入。
注4:可以用 DFView.exe 打開 MSWORD 的 DOC 文件進行復合文件的瀏覽。但是該程序并沒有實現國際化,不能打開中文文件名的復合文件,因此需要改名后才能瀏覽。
注5:CLSID,在后續的文章中介紹。
注6:關于 COM 中內存使用的問題,在后續的文章中介紹。

posted on 2012-10-17 22:23 jackdong 閱讀(410) 評論(0)  編輯 收藏 引用 所屬分類: Windows編程
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久福利视频| 久久不射中文字幕| 黄色成人精品网站| 一本久久a久久精品亚洲| 中国亚洲黄色| 99成人精品| 欧美好吊妞视频| 一本一本久久a久久精品牛牛影视| 欧美天天影院| 亚洲精品国产精品久久清纯直播 | 午夜久久久久久| 亚洲国产导航| 久久久综合网站| av不卡在线看| 欧美日韩一区二区在线观看| 国产精品一区视频网站| 国产精品久久久久久妇女6080 | 亚洲欧洲日本国产| 久久精品一级爱片| 欧美视频一区二区三区…| 久久人人精品| 六月天综合网| 欧美精品成人| 伊人成人在线视频| 午夜精品久久久久久久久久久久| 一区二区三区国产精华| 日韩午夜在线| 久久国产免费| 国产精品欧美久久| 日韩亚洲精品视频| 亚洲一区免费| 欧美日韩亚洲一区二| 亚洲激情图片小说视频| 另类激情亚洲| 国产欧美一区二区精品秋霞影院| 亚洲伊人伊色伊影伊综合网| 免费成人性网站| 欧美日韩亚洲一区| 亚洲精品中文字| 久久大香伊蕉在人线观看热2| 亚洲人成在线播放| 日韩视频在线观看国产| 美乳少妇欧美精品| 欧美另类专区| 久久久久国产精品麻豆ai换脸| 国产欧美一区二区视频| 国产精品一级| 欧美成人a∨高清免费观看| 欧美二区在线播放| 欧美成人免费全部观看天天性色| 99在线热播精品免费| 亚洲男人影院| 久久国产精品99国产| 亚洲精品国久久99热| 午夜精品久久久久久久久久久久 | 在线一区日本视频| 国产精品第一区| 欧美一区二区三区啪啪| 欧美韩日视频| 久久爱www久久做| 午夜精品视频在线| 国产女优一区| 久久久国产精品一区二区三区| 欧美本精品男人aⅴ天堂| 久久久久久夜| 午夜视频一区| 国产情侣一区| 亚洲一区精品在线| 亚洲第一精品夜夜躁人人躁 | 亚洲美女电影在线| 性色av一区二区三区红粉影视| 国产精品日韩一区二区| 午夜视频精品| 欧美另类videos死尸| 亚洲开发第一视频在线播放| 一个色综合导航| 国产精品久久久久久久久久免费看 | 欧美色图五月天| 亚洲一区视频| 欧美日韩中字| 久热精品视频在线观看| 国产精品激情av在线播放| 亚洲国产va精品久久久不卡综合| 亚洲欧美电影在线观看| 欧美视频网址| 蜜臀99久久精品久久久久久软件| 国产一区深夜福利| 一区二区三区产品免费精品久久75 | 国产一区再线| 久久女同互慰一区二区三区| 在线观看一区| 国产网站欧美日韩免费精品在线观看| 麻豆精品91| 亚洲第一精品久久忘忧草社区| 久久久精品欧美丰满| aa级大片欧美| 欧美二区视频| 久久综合给合久久狠狠狠97色69| 欧美激情视频一区二区三区在线播放 | 欧美日本在线| 老司机一区二区| 一二美女精品欧洲| 国产午夜精品全部视频播放| 欧美成人a视频| 一区二区三区波多野结衣在线观看| 性娇小13――14欧美| 亚洲黄色av一区| 欧美日韩一区在线视频| 久久久国产91| 欧美一二三区在线观看| 亚洲精品在线三区| 欧美午夜精品久久久久免费视| 亚洲一区二区三区久久| 亚洲精品综合久久中文字幕| 男女激情久久| 久久一本综合频道| 亚洲视频你懂的| 香蕉精品999视频一区二区| 亚洲精品久久久久久久久久久| 亚洲激情影院| 在线观看三级视频欧美| 亚洲高清视频一区二区| 亚洲免费视频一区二区| 欧美日韩综合| 在线不卡中文字幕| 欧美国产乱视频| 亚洲品质自拍| 亚洲九九精品| 欧美激情麻豆| 一本久久综合亚洲鲁鲁五月天| 国产精品一区二区在线观看网站| 久久福利精品| 国产精品扒开腿爽爽爽视频| 国产麻豆综合| 久久久久久夜| 精品999在线观看| 亚洲精品视频在线看| 日韩午夜av在线| 久久综合色影院| 亚洲国产裸拍裸体视频在线观看乱了中文 | 狠狠色丁香久久婷婷综合丁香| 欧美日韩妖精视频| 国产美女精品一区二区三区| 亚洲精品视频在线观看免费| 麻豆精品网站| 亚洲永久在线| 一区二区三区自拍| 亚洲国产精品第一区二区| 国产精品亚洲综合天堂夜夜| 合欧美一区二区三区| 99在线热播精品免费| 亚洲精品久久久久久久久久久| 欧美黄色影院| 欧美制服第一页| 欧美日韩p片| 99国产精品99久久久久久粉嫩| 欧美国产专区| 欧美成人一区二区在线| 99精品国产高清一区二区| 一本色道婷婷久久欧美| 欧美成人免费一级人片100| 伊人一区二区三区久久精品| 亚洲人成在线播放网站岛国| 美女主播精品视频一二三四| 国产真实乱偷精品视频免| 欧美成年人网站| 午夜一级在线看亚洲| 日韩网站在线观看| 麻豆免费精品视频| 99国产精品| 午夜在线成人av| 在线观看国产成人av片| 亚洲欧洲精品一区| 午夜精品久久久久久久久久久久久| 国产综合色一区二区三区| 日韩视频精品在线观看| 国产欧美一区二区三区国产幕精品| 老牛嫩草一区二区三区日本| 国产精品av一区二区| 久久精品99国产精品酒店日本| 亚洲精品一区二区三区99| 日韩视频永久免费观看| 亚洲缚视频在线观看| 国内精品一区二区三区| 亚洲精品美女91| 亚洲一区二区三区精品动漫| 日韩一区二区久久| 亚洲欧洲在线播放| 久久亚洲精品中文字幕冲田杏梨| 一区二区三区你懂的| 欧美久久久久久| 欧美一级专区免费大片| 亚洲乱码精品一二三四区日韩在线 | 国产精品国产三级国产专播品爱网 | 久久天天躁狠狠躁夜夜爽蜜月 | 亚洲国产精品精华液网站| 久久午夜激情| 亚洲精品久久久久久久久久久久久| 欧美精品激情在线| 亚洲成人自拍视频|