亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Delphi 中內(nèi)存映射對(duì)于大文件的使用

 更新時(shí)間:2017年09月03日 15:32:37   作者:bdmh  
這篇文章主要介紹了Delphi 中內(nèi)存映射對(duì)于大文件的使用的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下

Delphi 中內(nèi)存映射對(duì)于大文件的使用

平時(shí)很少使用大文件的內(nèi)存映射,碰巧遇到了這樣的要求,所以把過(guò)程記錄下來(lái),當(dāng)給各位一個(gè)引子吧,因?yàn)閼?yīng)用不算復(fù)雜,可能有考慮不到的地方,歡迎交流。

對(duì)于一些小文件,用普通的文件流就可以很好的解決,可是對(duì)于超大文件,比如2G或者更多,文件流就不行了,所以要使用API的內(nèi)存映射的相關(guān)方法,即使是內(nèi)存映射,也不能一次映射全部文件的大小,所以必須采取分塊映射,每次處理一小部分。

 先來(lái)看幾個(gè)函數(shù)

CreateFile :打開(kāi)文件

GetFileSize : 獲取文件尺寸

CreateFileMapping :創(chuàng)建映射

MapViewOfFile :映射文件

看MapViewOfFile的幫助,他的最后兩個(gè)參數(shù)都需要是頁(yè)面粒度的整數(shù)倍,一般機(jī)器的頁(yè)面粒度為64k(65536字節(jié)),而我們實(shí)際操作中,一般都不是這樣規(guī)矩的,任意位置,任意長(zhǎng)度都是可能的,所以就要做一些處理。

本例的任務(wù)是從一個(gè)長(zhǎng)度列表中(FInfoList),依次讀取長(zhǎng)度值,然后到另外一個(gè)大文件(FSourceFileName)中去順序讀取指定長(zhǎng)度的數(shù)據(jù),如果是小文件,這個(gè)就好辦了,一次讀到文件流中,然后依次讀取就是了,大數(shù)對(duì)于大文件,就需要不斷改變映射的位置,來(lái)取得我們想要的數(shù)據(jù)。

本例中顯示先通過(guò)GetSystemInfo來(lái)獲取頁(yè)面粒度,然后以10倍的頁(yè)面粒度為一個(gè)映射數(shù)據(jù)塊,在for循環(huán)中,會(huì)判斷已經(jīng)讀取的長(zhǎng)度(totallen)加上即將讀取的長(zhǎng)度,是否在本次映射范圍之內(nèi)(10倍的頁(yè)面粒度),如果在就繼續(xù)讀取,如果超出了,就要記下剩下的數(shù)據(jù),然后重新映射下一塊內(nèi)存,并將記錄下的剩余數(shù)據(jù)合并到新讀取的數(shù)據(jù)中,有點(diǎn)繞?。赡苁俏业南敕ㄌ@了),

下面列出代碼。

procedure TGetDataThread.DoGetData; 
var 
 FFile_Handle:THandle; 
 FFile_Map:THandle; 
 list:TStringList; 
 p:PChar; 
 i,interval:Integer; 
begin 
 try 
 totallen := 0; 
 offset := 0; 
 tstream := TMemoryStream.Create; 
 stream := TMemoryStream.Create; 
 list := TStringList.Create; 
 //獲取系統(tǒng)信息 
 GetSystemInfo(sysinfo); 
 //頁(yè)面分配粒度大小 
 blocksize := sysinfo.dwAllocationGranularity; 
 //打開(kāi)文件 
 FFile_Handle := CreateFile(PChar(FSourceFileName),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); 
 if FFile_Handle = INVALID_HANDLE_VALUE then Exit; 
 //獲取文件尺寸 
 filesize := GetFileSize(FFile_Handle,nil); 
 //創(chuàng)建映射 
 FFile_Map := CreateFileMapping(FFile_Handle,nil,PAGE_READONLY,0,0,nil); 
 if FFile_Map = 0 then Exit; 
 //此處我們已10倍blocksize為一個(gè)數(shù)據(jù)塊來(lái)映射,如果文件尺寸小于10倍blocksize,則直接映射整個(gè)文件長(zhǎng)度 
 if filesize div blocksize > 10 then 
  readlen := 10*blocksize 
 else 
  readlen := filesize; 
 for i := 0 to FInfoList.Count - 1 do 
 begin 
  list.Delimiter := ':'; 
  list.DelimitedText := FInfoList.Strings[i]; 
  //取得長(zhǎng)度,我這里做了解析,因?yàn)槲掖鎯?chǔ)的信息為 a:b:c 這種類(lèi)型,所以以:號(hào)分隔 
  len := StrToInt(list.Strings[1]); 
  interval := StrToInt(list.Strings[2]); 
  if (i = 0) or (totallen+len >=readlen) then 
  begin 
   //如果已讀取的長(zhǎng)度加上即將要讀取的長(zhǎng)度大于 10倍blocksize,那么我們要保留之前映射末尾的內(nèi)容,以便和新映射的內(nèi)容合并 
   if i > 0 then 
   begin 
    offset := offset + readlen; 
    //寫(xiě)入臨時(shí)流 
    tstream.Write(p^,readlen-totallen); 
    tstream.Position := 0; 
   end; 
   //如果未讀取的數(shù)據(jù)長(zhǎng)度已經(jīng)不夠一個(gè)分配粒度,那么就直接映射剩下的長(zhǎng)度 
   if filesize-offset < blocksize then 
    readlen := filesize-offset; 
   //映射,p是指向映射區(qū)域的指針 
   //注意這里第三個(gè)參數(shù),一直設(shè)為0,這個(gè)值要根據(jù)實(shí)際情況設(shè)置 
   p := PChar(MapViewOfFile(FFile_Map,FILE_MAP_READ,0,offset,readlen)); 
  end; 
  //如果臨時(shí)流中有數(shù)據(jù),需要合并 
  if tstream.Size > 0 then 
  begin 
   //把臨時(shí)流數(shù)據(jù)copy過(guò)來(lái) 
   stream.CopyFrom(tstream,tstream.Size); 
   //然后在末尾寫(xiě)入新數(shù)據(jù),合并完成 
   stream.Write(p^,len-tstream.Size); 
   totallen := len-tstream.Size; 
   //移動(dòng)指針的位置,指向下一個(gè)數(shù)據(jù)的開(kāi)始 
   Inc(p,len-tstream.Size); 
   tstream.Clear; 
  end 
  else 
  begin 
   stream.Write(p^,len); 
   totallen := totallen + len; 
   Inc(p,len); 
  end; 
  stream.Position := 0; 
  //將流保存成文件 
  stream.SaveToFile(IntToStr(i)+'.txt'); 
  stream.Clear; 
 end; 
 finally 
  stream.Free; 
  tstream.Free; 
  CloseHandle(FFile_Handle); 
  CloseHandle(FFile_Map); 
 end; 
end; 

如有疑問(wèn)請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • delphi程序全屏顯示無(wú)標(biāo)題欄覆蓋整個(gè)屏幕(適合屏保)

    delphi程序全屏顯示無(wú)標(biāo)題欄覆蓋整個(gè)屏幕(適合屏保)

    delphi 簡(jiǎn)單實(shí)現(xiàn)程序全屏顯示無(wú)標(biāo)題欄,覆蓋整個(gè)屏幕,這個(gè)在做工控機(jī)或屏保時(shí)有用的,具體代碼如下,感興趣的朋友可以參考下哈
    2013-06-06
  • Delphi下OpenGL2d繪圖之畫(huà)點(diǎn)的方法

    Delphi下OpenGL2d繪圖之畫(huà)點(diǎn)的方法

    這篇文章主要介紹了Delphi下OpenGL2d繪圖之畫(huà)點(diǎn)的方法,需要的朋友可以參考下
    2014-07-07
  • 在Delphi實(shí)現(xiàn)在數(shù)據(jù)庫(kù)中存取圖像的圖文演示無(wú)錯(cuò)

    在Delphi實(shí)現(xiàn)在數(shù)據(jù)庫(kù)中存取圖像的圖文演示無(wú)錯(cuò)

    最近打算學(xué)習(xí)Delphi實(shí)現(xiàn)在數(shù)據(jù)庫(kù)中存取圖像,網(wǎng)上的好多Delphi實(shí)現(xiàn)在數(shù)據(jù)庫(kù)中存取圖像都是錯(cuò)誤的,所以我把圖片給弄好了。
    2008-01-01
  • Delphi Command模式

    Delphi Command模式

    最近學(xué)習(xí)模式入迷, 所以就想寫(xiě)一篇關(guān)于模式的文章,這篇文章是<<Java 與模式>> (閻宏 著)里的一個(gè)例子, 我把它改成Delphi的.第一次寫(xiě)東西, 有不足之處希望大家可以諒解.
    2008-03-03
  • Delphi控件ListView的屬性及使用方法詳解

    Delphi控件ListView的屬性及使用方法詳解

    這篇文章主要介紹了Delphi控件ListView的屬性及使用方法詳解,對(duì)于Delphi控件ListView做一復(fù)習(xí)總結(jié),需要的朋友可以參考下
    2014-07-07
  • 初探Delphi中的插件編程

    初探Delphi中的插件編程

    前言我寫(xiě)Delphi程序是從MIS系統(tǒng)入門(mén)的,開(kāi)始嘗試子系統(tǒng)劃分的時(shí)候采用的是MDI窗體的結(jié)構(gòu)。隨著系統(tǒng)功能的擴(kuò)充,不斷有新的子系統(tǒng)加入系統(tǒng)中,單個(gè)工程會(huì)變得非常大,每次做一點(diǎn)修改都要重新編譯,單個(gè)工程的形式也不利于團(tuán)隊(duì)協(xié)作。為了提高工作效率,我希望利用DLL動(dòng)態(tài)鏈接庫(kù)的形式實(shí)現(xiàn)插件結(jié)構(gòu)的編程。
    2008-03-03
  • Delphi中設(shè)置條件斷點(diǎn)的方法講解

    Delphi中設(shè)置條件斷點(diǎn)的方法講解

    這篇文章主要介紹了Delphi中設(shè)置條件斷點(diǎn)的方法,有需要的朋友可以參考一下
    2014-01-01
  • Delphi 中內(nèi)存映射對(duì)于大文件的使用

    Delphi 中內(nèi)存映射對(duì)于大文件的使用

    這篇文章主要介紹了Delphi 中內(nèi)存映射對(duì)于大文件的使用的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • mybatis in foreach雙層嵌套的問(wèn)題解決

    mybatis in foreach雙層嵌套的問(wèn)題解決

    在使用MyBatis進(jìn)行數(shù)據(jù)庫(kù)操作時(shí),有時(shí)候需要處理雙層嵌套的數(shù)據(jù)結(jié)構(gòu),本文主要介紹了mybatis in foreach雙層嵌套的問(wèn)題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • wordpress主題支持自定義菜單及修改css樣式實(shí)現(xiàn)方法

    wordpress主題支持自定義菜單及修改css樣式實(shí)現(xiàn)方法

    使用wordpress過(guò)程中會(huì)遇到主題支持自定義菜單以及修改css樣式問(wèn)題,本文將介紹詳細(xì)解決方法,需要朋友可以參考下
    2012-12-12

最新評(píng)論