• <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>
            隨筆 - 64, 文章 - 11, 評(píng)論 - 12, 引用 - 0
            數(shù)據(jù)加載中……

            三種操作文件存儲(chǔ)方案的比較

                       這段時(shí)間,我正在負(fù)責(zé)升級(jí)公司中一個(gè)產(chǎn)品的幾個(gè)版本。這幾個(gè)系統(tǒng)的基本框架都相同,架構(gòu)都是以第一個(gè)系統(tǒng)為模型,只是后續(xù)的產(chǎn)品擴(kuò)展了許多功能。總的說(shuō)來(lái)這幾個(gè)產(chǎn)品邏輯也不是很復(fù)雜,但因幾易開發(fā)員,而且沒有標(biāo)準(zhǔn)和缺乏設(shè)計(jì),所以系統(tǒng)的可維護(hù)性較低。

                     上個(gè)星期,我重構(gòu)了產(chǎn)品中的文件操作方案。原有的操作方案是先以讀的方式打開原文件,而后從該文件中不斷地讀取指定緩沖大小的內(nèi)容,并對(duì)讀取的字串進(jìn)行處理,把處理過(guò)后的內(nèi)容寫入到一個(gè)臨時(shí)文件中,最后把原文件刪除而把臨時(shí)文件更名為原文件名。個(gè)人基于如下的考慮認(rèn)為這種方案不適于當(dāng)前場(chǎng)景:(1)需修改一條內(nèi)容時(shí),得從文件頭一條一條地讀取出來(lái),然后判斷是修改或者是刪除,或者是沒有找到則是增加。(2)這種方案對(duì)于刪除、修改操作都要先逐條地移動(dòng)記錄到臨時(shí)文件,而后再重命名,所以這種方案對(duì)于大文件或者是經(jīng)常修改的文件是不合適的。(3)由于這塊文件操作是多線程的,那么可以假設(shè)一個(gè)場(chǎng)景 ,TA線程以共享讀的方式打開了文件,然后轉(zhuǎn)化到了臨時(shí)文件,關(guān)閉兩個(gè)文件句柄,TA停止。這時(shí)TB也打開原有文件并讀取了一段內(nèi)容,并打開重寫了臨時(shí)文件,接著TB又停止并關(guān)閉了文件句柄。TA繼續(xù)工作,刪除原文件重命名臨時(shí)文件,這時(shí)TB線程讀了臟數(shù)據(jù)而TA就有可能提交了錯(cuò)誤的數(shù)據(jù)。當(dāng)然這種情況是我推理出來(lái)的,實(shí)際是很少出現(xiàn)的,問(wèn)題肯定是存在的。有關(guān)的這種文件操作方式的其它缺點(diǎn)還可以查閱windows核心編程中的相關(guān)章節(jié)。其中也有相關(guān)的論述?;谏鲜龅姆治?,我決定重構(gòu)其實(shí)現(xiàn)。我提出了兩種備選方案,(1)采用XML的方式,對(duì)于文件鎖定的方案是以流的方式從獨(dú)占的文件中讀取,完成操作寫入時(shí)關(guān)閉。采用這種方式有利于查找、修改、刪除和添加。因?yàn)?/span>XML文件要先載入內(nèi)存并解析成DOM樹,所以XML文件較大時(shí)就不適合。(2)以獨(dú)占方式打開文件,采用內(nèi)存映射的方式操作,完成操作后寫回并關(guān)閉。在創(chuàng)建映射內(nèi)核對(duì)象時(shí)以原文件大小再加一個(gè)適當(dāng)?shù)脑隽?,最后根?jù)實(shí)際的大小截?cái)辔募Mㄟ^(guò)比較這兩種方案在執(zhí)行50000條記錄時(shí),都是1500ms這內(nèi)。最后,基于與原有格式的兼容性和可能會(huì)出現(xiàn)大文件的考慮,我選擇了內(nèi)存映射方式。通過(guò)此次重構(gòu),大大提高了系統(tǒng)的運(yùn)行效率和穩(wěn)定性。

                     代碼如下,供大家點(diǎn)評(píng)。

             1//頭文件
             2#pragma once
             3
             4class ShadowDirText
             5{
             6public:
             7    ShadowDirText(LPCTSTR szId);
             8    virtual ~ShadowDirText(void);
             9
            10private:
            11    ShadowDirText(const ShadowDirText &);
            12    ShadowDirText& operator=(const ShadowDirText &);
            13
            14public:
            15    static bool GetDirShadowListFilePath(LPCTSTR szDirPath, CString &strPath);
            16    static bool Exists(LPCTSTR szDirPath);
            17    static bool Create(LPCTSTR szDirPath);
            18    static bool Delete(LPCTSTR szDirPath);
            19    static void SetFileName(LPCTSTR szName);
            20    
            21    bool Open(LPCTSTR szDirPath);
            22    void Close();
            23    bool RemoveRecord(LPCTSTR szPath, bool bDir);
            24    bool AddRecord(LPCTSTR szPath, bool bDir);
            25    bool ExistRecord(LPCTSTR szPath, bool bDir);
            26
            27    bool RemoveAll();
            28
            29private:
            30    DWORD Find(LPCTSTR szPath, bool bDir);
            31    bool  FindLineById(DWORD dwSearchPosition, DWORD &dwBegin, DWORD &dwEnd);
            32    void FillEnd();
            33
            34private:
            35    CString m_strId;
            36    CString m_strDir;
            37    HANDLE m_hFile;
            38    HANDLE m_hFileMapping;
            39    PVOID m_pvMapView;
            40    DWORD m_dwFileSize;
            41    DWORD m_dwOriginalSize;
            42
            43    static const int m_snExtened;
            44    static TCHAR m_sszFileName[_MAX_FNAME];
            45    static const CString m_sstrFormatting; 
            46    static const TCHAR m_sszLineEnd[2];
            47}
            ;
            48

              1#include "StdAfx.h"
              2#include "ShadowDirText.h"
              3
              4//////////////////////////////////////////////////////////////////////////
              5// Constraint and static variable
              6//
              7//
              8//////////////////////////////////////////////////////////////////////////
              9const int ShadowDirText::m_snExtened =102400//100KB
             10TCHAR ShadowDirText::m_sszFileName[_MAX_FNAME] = {_T('\0')};
             11
             12// attention:
             13// m_sstrFormatting and m_sszLineEnd must have the same end symbols.
             14//
             15const CString ShadowDirText::m_sstrFormatting = _T("id=\"%s\",name=\"%s\",isdir=\"%d\"\r\n");
             16const TCHAR ShadowDirText::m_sszLineEnd[2= {_T('\r'), _T('\n')};
             17
             18//////////////////////////////////////////////////////////////////////////
             19// Constructor and Destructor
             20//
             21//
             22//////////////////////////////////////////////////////////////////////////
             23ShadowDirText::ShadowDirText(LPCTSTR szId)
             24:    m_strId(szId)
             25{
             26    m_hFile = NULL;
             27    m_hFileMapping = NULL;
             28    m_pvMapView = NULL;
             29    m_dwFileSize = 0;
             30}

             31
             32ShadowDirText::~ShadowDirText(void)
             33{
             34    Close();
             35}

             36
             37//////////////////////////////////////////////////////////////////////////
             38// public static methods
             39//
             40//
             41//////////////////////////////////////////////////////////////////////////
             42
             43bool ShadowDirText::GetDirShadowListFilePath(LPCTSTR szDirPath, CString &strPath)
             44{
             45    ATLASSERT(szDirPath && 
             46        _T("argument 'szDirPath' of ShadowDirListHelper::GetDirShadowListFilePath is null."));
             47
             48    strPath = szDirPath;
             49    if(strPath.GetLength() == 0)
             50    {
             51        return false;
             52    }

             53    if(strPath.GetAt(strPath.GetLength() -1!= _T('\\'))
             54    {
             55        strPath.AppendChar(_T('\\'));
             56    }

             57    if(!PathFileExists(strPath))
             58    {
             59        return false;
             60    }

             61    strPath.Append(m_sszFileName);
             62    return true;
             63}

             64
             65bool ShadowDirText::Exists( LPCTSTR szDirPath )
             66{
             67    CString strPath;
             68    if(!GetDirShadowListFilePath(szDirPath, strPath))
             69    {
             70        return false;
             71    }

             72    if(!PathFileExists(strPath))
             73    {
             74        return false;
             75    }

             76    return true;
             77}

             78
             79bool ShadowDirText::Create(LPCTSTR szDirPath)
             80{
             81    CString strPath;
             82    if(!GetDirShadowListFilePath(szDirPath, strPath))
             83    {
             84        return false;
             85    }

             86    if(!PathFileExists(strPath))
             87    {
             88        HANDLE handle = CreateFile(strPath,
             89            GENERIC_READ | GENERIC_WRITE,
             90            0,
             91            NULL,
             92            OPEN_ALWAYS,
             93            FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE,
             94            NULL);
             95        if(INVALID_HANDLE_VALUE == handle)
             96        {
             97            return false;
             98        }

             99        static BYTE unicodeHeader[]= {0xff0xfe};
            100        static TCHAR szEnd[] = _T("\r\n");
            101        DWORD dwWrited = 0;
            102        WriteFile(handle, unicodeHeader, sizeof(unicodeHeader), &dwWrited,0);
            103        WriteFile(handle,szDirPath, (DWORD)(_tcslen(szDirPath) * sizeof(TCHAR)), &dwWrited, 0);
            104        WriteFile(handle, szEnd, (DWORD)(_tcslen(szEnd) * sizeof(TCHAR)), &dwWrited, 0);
            105        CloseHandle(handle);
            106    }

            107    return true;
            108}

            109
            110bool ShadowDirText::Delete( LPCTSTR szDirPath )
            111{
            112    CString strPath;
            113    if(!GetDirShadowListFilePath(szDirPath, strPath))
            114    {
            115        return true;
            116    }

            117    if(PathFileExists(strPath))
            118    {
            119        if(!DeleteFile(strPath))
            120        {
            121            return false;
            122        }

            123    }

            124    return true;
            125}

            126
            127void ShadowDirText::SetFileName( LPCTSTR szName )
            128{
            129    ATLASSERT(szName && _T("argument of ShadowDirListHelper::SetFileName is NULL"));
            130    _tcscpy_s(m_sszFileName,_MAX_FNAME, szName);
            131}

            132//////////////////////////////////////////////////////////////////////////
            133// public methods
            134//
            135//
            136//////////////////////////////////////////////////////////////////////////
            137bool ShadowDirText::Open(LPCTSTR szDirPath )
            138{
            139    CString strPath;
            140    if(!GetDirShadowListFilePath(szDirPath, strPath))
            141    {
            142        return false;
            143    }

            144    if(!PathFileExists(strPath))
            145    {
            146        if(!Create(szDirPath))
            147        {
            148            return false;
            149        }

            150    }

            151    Close();
            152    m_strDir = szDirPath;
            153    m_hFile = CreateFile(strPath, 
            154        GENERIC_READ | GENERIC_WRITE, 
            155        0
            156        NULL, 
            157        OPEN_EXISTING, 
            158        FILE_ATTRIBUTE_HIDDEN, 
            159        0);
            160    if(INVALID_HANDLE_VALUE == m_hFile)
            161    {
            162        return false;
            163    }

            164    m_dwOriginalSize = m_dwFileSize = GetFileSize(m_hFile, NULL);
            165    m_hFileMapping = CreateFileMapping(m_hFile, 
            166        NULL, 
            167        PAGE_READWRITE, 
            168        0
            169        m_dwFileSize + m_snExtened, 
            170        0);
            171    if(NULL == m_hFileMapping)
            172    {
            173        Close();
            174        return false;
            175    }

            176    m_pvMapView = MapViewOfFile(m_hFileMapping, FILE_MAP_ALL_ACCESS, 000);
            177    if(NULL == m_pvMapView)
            178    {
            179        Close();
            180        return false;
            181    }

            182    m_pvMapView = (char*)m_pvMapView + 2;
            183    m_dwFileSize -= 2;
            184    FillEnd();
            185    return true;
            186}

            187
            188void ShadowDirText::Close()
            189{
            190    if(m_pvMapView)
            191    {
            192        m_pvMapView = (char*)m_pvMapView - 2;
            193        ::UnmapViewOfFile(m_pvMapView);
            194        m_pvMapView = NULL;
            195    }

            196    if(m_hFileMapping)
            197    {
            198        CloseHandle(m_hFileMapping);
            199        m_hFileMapping = NULL;
            200    }

            201    if(m_hFile)
            202    {
            203        SetFilePointer(m_hFile, m_dwFileSize + 2, NULL, FILE_BEGIN);
            204        SetEndOfFile(m_hFile);
            205        CloseHandle(m_hFile);
            206        m_hFile = NULL;
            207    }

            208}

            209
            210bool ShadowDirText::RemoveRecord( LPCTSTR szPath, bool bDir)
            211{
            212    DWORD dwPosition = Find(szPath, bDir);
            213    if(0 == dwPosition)
            214    {
            215        return true;
            216    }

            217    CString strTemp;
            218    strTemp.Format(m_sstrFormatting, m_strId, szPath, (bDir? 10));
            219    int nLength = strTemp.GetLength() * sizeof(TCHAR);
            220    char *pBegin = (char*)m_pvMapView;
            221    memmove_s(pBegin + dwPosition, m_dwFileSize - dwPosition,pBegin + dwPosition + nLength, 
            222        m_dwFileSize - dwPosition);
            223    m_dwFileSize -= nLength;
            224    FillEnd();
            225    return true;
            226}

            227
            228bool ShadowDirText::AddRecord(LPCTSTR szPath, bool bDir)
            229{
            230    DWORD dwPosition = Find(szPath, bDir);
            231    if(0 != dwPosition)
            232    {
            233        return true;
            234    }

            235    CString strTemp;
            236    strTemp.Format(m_sstrFormatting, m_strId, szPath, (bDir? 10));
            237    int nLength = strTemp.GetLength() * sizeof(TCHAR);
            238    if(m_dwFileSize + nLength + 2 > m_dwOriginalSize + m_snExtened)
            239    {
            240        Close();
            241        Open(m_strDir);
            242        return AddRecord(szPath, bDir);    
            243    }

            244    char *pBegin = (char*)m_pvMapView;
            245    TCHAR *pWriten=(TCHAR*)(pBegin + m_dwFileSize);
            246    memcpy_s(pWriten, nLength + sizeof(TCHAR), strTemp, nLength);
            247    m_dwFileSize += nLength;
            248    FillEnd();
            249    return true;
            250}

            251
            252bool ShadowDirText::ExistRecord( LPCTSTR szPath, bool bDir)
            253{
            254    return (Find(szPath, bDir)? truefalse);
            255}

            256
            257bool ShadowDirText::RemoveAll()
            258{
            259    DWORD dwSearchPosition = 0;
            260    DWORD dwBegin = 0;
            261    DWORD dwEnd = 0;
            262    bool bRet = true;
            263    while (FindLineById(dwSearchPosition, dwBegin, dwEnd))
            264    {
            265        if(dwEnd > dwBegin)
            266        {
            267            char *pBegin = (char*)m_pvMapView;
            268            memmove_s(pBegin + dwBegin, m_dwFileSize - dwBegin,pBegin + dwEnd, 
            269                m_dwFileSize - dwBegin);
            270            m_dwFileSize -= (dwEnd - dwBegin);
            271            FillEnd();
            272        }

            273    }

            274    if (dwBegin >= m_dwFileSize || dwEnd > m_dwFileSize)
            275    {
            276        bRet = false;
            277    }

            278    return bRet;
            279}

            280//////////////////////////////////////////////////////////////////////////
            281// private methods
            282//
            283//
            284//////////////////////////////////////////////////////////////////////////
            285DWORD ShadowDirText::Find( LPCTSTR szPath, bool bDir )
            286{
            287    ATLASSERT(m_pvMapView != NULL && _T("Map file base address is invalid."));
            288    if(NULL == m_pvMapView)
            289    {
            290        return 0;
            291    }

            292    CString strTemp;
            293    strTemp.Format(m_sstrFormatting, m_strId, szPath, (bDir? 10));
            294    TCHAR *pBegin =(TCHAR*)m_pvMapView;
            295    TCHAR *= _tcsstr(pBegin, strTemp);
            296    if(!p)
            297    {
            298        return 0;
            299    }

            300    DWORD dwOffset = (DWORD)(p - pBegin) * sizeof(TCHAR);
            301    if(dwOffset >= m_dwFileSize)
            302    {
            303        return 0;
            304    }

            305    return dwOffset;
            306}

            307
            308void ShadowDirText::FillEnd()
            309{
            310    char *pBegin = (char*)m_pvMapView;
            311    TCHAR *pWriten=(TCHAR*)(pBegin + m_dwFileSize);
            312    *pWriten = 0;
            313}

            314
            315bool ShadowDirText::FindLineById( DWORD dwSearchPosition, DWORD &dwBegin, DWORD &dwEnd )
            316{
            317    ATLASSERT(dwSearchPosition % sizeof(TCHAR) == 0 && 
            318        _T("argument \"dwSearchPosition\" of ShadowDirText::FindLineById must be even"));
            319    dwBegin = 0;
            320    dwEnd = 0;
            321    if(dwSearchPosition % sizeof(TCHAR))
            322    {
            323        return true;
            324    }

            325    CString str;
            326    str.Format(_T("id=\"%s\""), m_strId);
            327    TCHAR *pBegin = (TCHAR *)((char*)m_pvMapView + dwSearchPosition);
            328    TCHAR *p1 = _tcsstr(pBegin, str);
            329    if(!p1)
            330    {
            331        return false;
            332    }

            333    dwBegin = dwSearchPosition + (p1 - pBegin) * sizeof(TCHAR);
            334    TCHAR *p2 = _tcsstr(p1, m_sszLineEnd);
            335    if(!p2)
            336    {
            337        dwEnd = m_dwFileSize;
            338    }

            339    else
            340    {
            341        dwEnd = dwBegin + (p2 - p1) * sizeof(TCHAR) + sizeof(m_sszLineEnd);
            342    }

            343    if(dwBegin >= m_dwFileSize || dwEnd > m_dwFileSize)
            344    {
            345        ATLASSERT(_T("the end of memory was bad."));
            346        return false;
            347    }

            348    return true;
            349}

                  由于篇幅太長(zhǎng),我就不貼上XML文件操作的封裝類。在上面的代碼中str.Format(_T("id=\"%s\""), m_strId);這語(yǔ)句應(yīng)提取出來(lái)以提高可維護(hù)性。這里貼出的是評(píng)價(jià)方案時(shí)的類,并不是實(shí)際項(xiàng)目中的類。但總體上是一樣的,差別是完成了id, name,isdir等的常量及相關(guān)格式的標(biāo)準(zhǔn)化。

            posted on 2009-07-22 10:51 Robertxiao 閱讀(925) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Windows/MFC探索

            久久精品国产99久久无毒不卡| 国产精品对白刺激久久久| 久久综合久久性久99毛片| 四虎亚洲国产成人久久精品| 久久毛片免费看一区二区三区| 久久久国产亚洲精品| 亚洲午夜久久久久久噜噜噜| 久久婷婷五月综合色高清| 天天爽天天爽天天片a久久网| 久久成人国产精品一区二区| 久久人做人爽一区二区三区| 亚洲αv久久久噜噜噜噜噜| 欧美一区二区精品久久| 精品99久久aaa一级毛片| 中文成人久久久久影院免费观看| 99蜜桃臀久久久欧美精品网站| 国产一久久香蕉国产线看观看| 久久亚洲中文字幕精品一区| 国产成人精品久久| 26uuu久久五月天| 国产69精品久久久久APP下载| 久久精品中文字幕无码绿巨人| 久久成人精品| 久久久久久亚洲Av无码精品专口| 精品国产热久久久福利| 久久午夜无码鲁丝片秋霞| 国产成人精品久久二区二区| 久久亚洲中文字幕精品一区| 日韩精品无码久久久久久| 久久天天躁狠狠躁夜夜2020老熟妇| 久久精品国产久精国产果冻传媒| 大蕉久久伊人中文字幕| 亚洲中文久久精品无码ww16| 久久AAAA片一区二区| 久久亚洲AV成人无码电影| 亚洲精品国产综合久久一线| 国产精品久久久久久久久| 99久久精品国产一区二区 | 日韩精品久久久肉伦网站| 久久精品视屏| 国产精品久久影院|