用C語言讀取大檔案的問題 記憶體對映

2021-04-26 01:19:08 字數 3223 閱讀 2443

windows對檔案的讀寫提供了很豐富的操作手段,如:

1. file 

*fp, fstearm; (c/c

++)2. cfile, cstdiofile; (mfc)

3. createfile, readfile;(api)

在處理一般的檔案(文字

/非文字),這些足夠了。然而在處理比較大的檔案如

幾十m, 幾百m, 甚至上g的檔案, 這時再用一般手段處理,系統就顯的力不從心了

要把檔案讀出,再寫進,耗費的是cpu利用率與記憶體以及io的頻繁操作。這顯然是

令使用者難以忍受的

為了解決這個吃記憶體,佔cpu,以及io瓶頸,windows核心程式設計提供了記憶體對映檔案技術

(maping file)

至於maping file是什麼原理,我不多說了,網上**資源一籮筐,我只想從應用層

來考慮,怎樣用這個技術,實現日常專案中的應用

舉例來說:

可能專案中,會經常用到一些大量的常量,而這些大量常量用巨集來替**再原始檔中

顯然不可取,一般是寫在檔案中,給常量一些編號,通過編號來索引

一般檔案比較小時候,常用做法也是先預讀到記憶體中,畢竟從記憶體中讀比從檔案中讀要快(io操作的瓶頸)

比較好的做法,讀到stl map 中去:

例如乙個索引檔案:

seu07201213

=汪洋中的一片葉子

jiangsheng=蔣晟

seu07201214

=csdn

開啟檔案,解析

=號,在解析方面有cstring操作,strtok,strstr, boost 正規表示式匹配等等,但我比較喜歡

sscanf(szindex, 

"%[^=]=%[^=]

", sname, svalue);

sscanf(szindex, 

"%[^=]=%s

", sname, svalue);

fscanf(stream, 

"%[^=]=%[^=]

", sname, svalue);

之類,然後再定義乙個map:

map<

string

, string

>

m_map;

m_map[sname] 

=svalue;

但是檔案比較大的時候,筆者做過測試,用上面方法處理乙個15m, 25萬行的文字檔案,占用記憶體非常

的高,達70多m,處理的速度也非常的慢,這還不包括回寫到檔案

這時,maping file就派上用場了,這裡處理大檔案就拋棄了map的應用(因為容器占用很多記憶體)

而是直接利用字元指標來操作,不用其他封裝,不多說了,請看示例:

#pragma

warning(disable: 4786) 

#include 

<

windows.h

>

#include 

<

stdio.h

>

#include 

<

iostream

>

#include 

<

string

>

using

namespace

std;

string

getvalue(

const

tchar *, 

const

tchar 

*);  

//根據name得value

void

main(

intargc, 

char

*argv)

//建立檔案對映物件

handle hfilemap =0

, 0, null);

if(hfilemap 

==null)

//得到系統分配粒度

system_info sysinfo;

getsysteminfo(

&sysinfo);

dword dwgran 

=sysinfo.dwallocationgranularity;

//得到檔案尺寸

dword dwfilesizehigh;

__int64 qwfilesize 

=getfilesize(hfile, 

&dwfilesizehigh);

qwfilesize 

|=(((__int64)dwfilesizehigh) 

<<

32);

//關閉檔案物件

closehandle(hfile);

//偏移位址 

__int64 qwfileoffset =0

;//塊大小dword dwblockbytes 

=1000

*dwgran;

if(qwfilesize 

<

1000

*dwgran)

dwblockbytes 

=(dword)qwfilesize;

if(qwfileoffset 

>=0)

//-----------------------訪問資料開始-------------------------

cout

<<

getvalue(lpbmapaddress,

"seu07201213")

<<

endl;

getchar();

//-----------------------訪問資料結束-------------------------        

//撤銷檔案映像

unmapviewoffile(lpbmapaddress);}//

關閉檔案對映物件控制代碼

closehandle(hfilemap);    

}string

getvalue(

const

tchar 

*lpbmapaddress, 

const

tchar 

*sname)

return

svalue;

}以上實現了根據索引name匹配value的簡單過程,經測試,同樣25w行檔案,匹配耗費1秒不到,且

不占本程序記憶體。

以上修改lpbmapaddress任意處值,也不需要重新回寫到檔案,真正是大大提高了檔案讀與寫的效率

c語言學習筆記 記憶體管理 linux的記憶體映像

程式在記憶體中的儲存形式 程式儲存在flash中 程式在記憶體中主要分為以下幾段 段,資料段,唯讀資料段,bss段,堆,棧,檔案對映區,核心對映區 作業系統核心 程式一般存放在 段,在linux中又稱為文字段 資料段存放的一般是靜態變數和被初始化為非零值的全域性變數 bss段存放的是被初始化為零的全...

Python讀取大檔案的 坑「與記憶體占用檢測

python讀寫檔案的api都很簡單,一不留神就容易踩 坑 筆者記錄一次踩坑歷程,並且給了一些總結,希望到大家在使用python的過程之中,能夠避免一些可能產生隱患的 隨手搜尋python讀寫檔案的教程,很經常看到read 與readlines 這對函式。所以我們會常常看到如下 with open ...

TCP協議傳輸大檔案讀取時候的問題

大檔案傳不完的bug 我們在定義的時候定義服務端每次檔案讀取大小為10240,客戶端每次接受大小為10240 我們想當然的認為客戶端每次讀取大小就是10240而把客戶端的讀下來的檔案想當然大小每一次都加上10240 而實際上服務端傳送檔案send每次傳送不一定是一次性把10240的檔案傳送完,可能分...