• <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, 評論 - 12, 引用 - 0
            數據加載中……

            三種操作文件存儲方案的比較

                       這段時間,我正在負責升級公司中一個產品的幾個版本。這幾個系統的基本框架都相同,架構都是以第一個系統為模型,只是后續的產品擴展了許多功能。總的說來這幾個產品邏輯也不是很復雜,但因幾易開發員,而且沒有標準和缺乏設計,所以系統的可維護性較低。

                     上個星期,我重構了產品中的文件操作方案。原有的操作方案是先以讀的方式打開原文件,而后從該文件中不斷地讀取指定緩沖大小的內容,并對讀取的字串進行處理,把處理過后的內容寫入到一個臨時文件中,最后把原文件刪除而把臨時文件更名為原文件名。個人基于如下的考慮認為這種方案不適于當前場景:(1)需修改一條內容時,得從文件頭一條一條地讀取出來,然后判斷是修改或者是刪除,或者是沒有找到則是增加。(2)這種方案對于刪除、修改操作都要先逐條地移動記錄到臨時文件,而后再重命名,所以這種方案對于大文件或者是經常修改的文件是不合適的。(3)由于這塊文件操作是多線程的,那么可以假設一個場景 TA線程以共享讀的方式打開了文件,然后轉化到了臨時文件,關閉兩個文件句柄,TA停止。這時TB也打開原有文件并讀取了一段內容,并打開重寫了臨時文件,接著TB又停止并關閉了文件句柄。TA繼續工作,刪除原文件重命名臨時文件,這時TB線程讀了臟數據而TA就有可能提交了錯誤的數據。當然這種情況是我推理出來的,實際是很少出現的,問題肯定是存在的。有關的這種文件操作方式的其它缺點還可以查閱windows核心編程中的相關章節。其中也有相關的論述。基于上述的分析,我決定重構其實現。我提出了兩種備選方案,(1)采用XML的方式,對于文件鎖定的方案是以流的方式從獨占的文件中讀取,完成操作寫入時關閉。采用這種方式有利于查找、修改、刪除和添加。因為XML文件要先載入內存并解析成DOM樹,所以XML文件較大時就不適合。(2)以獨占方式打開文件,采用內存映射的方式操作,完成操作后寫回并關閉。在創建映射內核對象時以原文件大小再加一個適當的增量,最后根據實際的大小截斷文件。通過比較這兩種方案在執行50000條記錄時,都是1500ms這內。最后,基于與原有格式的兼容性和可能會出現大文件的考慮,我選擇了內存映射方式。通過此次重構,大大提高了系統的運行效率和穩定性。

                     代碼如下,供大家點評。

             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}

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

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

            国产精品午夜久久| 精品久久久久久久久久久久久久久| 粉嫩小泬无遮挡久久久久久| 综合人妻久久一区二区精品| 久久精品国产精品亚洲下载| 91精品久久久久久无码| 久久久久久久尹人综合网亚洲 | 91精品国产色综久久| 99久久超碰中文字幕伊人| 久久午夜无码鲁丝片| 亚洲成色www久久网站夜月| 精品久久久中文字幕人妻| 大香伊人久久精品一区二区| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 国产日韩久久免费影院| 久久亚洲精品中文字幕| 亚洲成av人片不卡无码久久 | 亚洲愉拍99热成人精品热久久| 久久乐国产精品亚洲综合| 亚洲国产精品一区二区久久| 精品国产99久久久久久麻豆 | 久久精品国产亚洲精品| 久久久久AV综合网成人| 国内精品久久人妻互换| 国产亚洲婷婷香蕉久久精品| 久久免费国产精品一区二区| 国产成人综合久久精品尤物| 久久99精品久久久久久野外| 久久久久亚洲AV无码专区桃色| 综合久久精品色| 久久久久久亚洲AV无码专区| 日本久久久久久中文字幕| 欧洲国产伦久久久久久久| 精产国品久久一二三产区区别| 久久久久成人精品无码中文字幕 | 日本精品久久久久影院日本| 久久久国产打桩机| 久久精品国产91久久麻豆自制| 亚洲а∨天堂久久精品| www性久久久com| 国产精品久久久久蜜芽|