文件操作(Win32, C++)

CFileUtils.h

#pragma once

#include <wtypesbase.h>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <tchar.h>

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

enum eFileAttributes
{
    eReadonly              = FILE_ATTRIBUTE_READONLY,
    eHidden                = FILE_ATTRIBUTE_HIDDEN,
    eSystem                = FILE_ATTRIBUTE_SYSTEM,
    eDirectory             = FILE_ATTRIBUTE_DIRECTORY,
    eArchive               = FILE_ATTRIBUTE_ARCHIVE,
    eDevice                = FILE_ATTRIBUTE_DEVICE,
    eNormal                = FILE_ATTRIBUTE_NORMAL,
    eTemporary             = FILE_ATTRIBUTE_TEMPORARY,
    eSparse_file           = FILE_ATTRIBUTE_SPARSE_FILE,
    eReparse_point         = FILE_ATTRIBUTE_REPARSE_POINT,
    eCompressed            = FILE_ATTRIBUTE_COMPRESSED,
    eOffline               = FILE_ATTRIBUTE_OFFLINE,
    eNot_content_indexed   = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
    eEncrypted             = FILE_ATTRIBUTE_ENCRYPTED,
    eIntegrity_stream      = FILE_ATTRIBUTE_INTEGRITY_STREAM,
    eVirtual               = FILE_ATTRIBUTE_VIRTUAL,
    eNo_scrub_data         = FILE_ATTRIBUTE_NO_SCRUB_DATA,
    eEa                    = FILE_ATTRIBUTE_EA,
    ePinned                = FILE_ATTRIBUTE_PINNED,
    eUnpinned              = FILE_ATTRIBUTE_UNPINNED,
    eRecall_on_open        = FILE_ATTRIBUTE_RECALL_ON_OPEN,
    eRecall_on_data_access = FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS,
};

typedef struct _FILEINFO
{
    _tstring m_fileDir;
    _tstring m_fileName;
    _tstring m_filePath;
    unsigned long long m_fileSize;
    DWORD m_fileAttributes;
    unsigned long long m_ftCreationTime;
    unsigned long long m_ftLastAccessTime;
    unsigned long long m_ftLastWriteTime;

    _FILEINFO() :
        m_fileSize(0),
        m_fileAttributes(0),
        m_ftCreationTime(0),
        m_ftLastAccessTime(0),
        m_ftLastWriteTime(0)
    {

    };
}FILEINFO;

class CFileUtils
{
public:
    //
    // @brief: 获取文件扩展名
    // @param: strfileName     文件名, 如: test.exe
    // @param: bIncludeDot     是否包含 . 号
    // @ret: 扩展名            如 test.exe bIncludeDot = false 时返回 exe, bIncludeDot = true 时返回 .exe, 
    static _tstring GetFileExtName(
        const _tstring& strfileName,
        bool bIncludeDot = false
    );

    //
    // @brief: 获取目录下文件路径
    // @param: fileList     文件路径字符串容器
    // @param: strDir          指定目录
    // @param: extList      扩展名过滤列表, 如: {("exe"), ("txt")}
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @param: bIgnoreCase  是否忽略扩展名过滤大小写
    // @ret: void
    static void GetFileList(
        std::vector<_tstring>& fileList,
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        bool bIgnoreCase = true
    );

    //
    // @brief: 获取目录下文件路径
    // @param: fileList     文件路径字符串容器
    // @param: strDir          指定目录
    // @param: extList      扩展名过滤列表, 如: {("exe"), ("txt")}
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @param: bIgnoreCase  是否忽略扩展名过滤大小写
    // @ret: void
    static void GetFileList(
        std::set<_tstring>& fileList,
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        bool bIgnoreCase = true
    );

    //
    // @brief: 获取目录下文件路径
    // @param: fileList     文件信息容器
    // @param: strDir          指定目录
    // @param: extList      扩展名过滤列表, 如: {("exe"), ("txt")}
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @param: bIgnoreCase  是否忽略扩展名过滤大小写
    // @ret: void
    static void GetFileList(
        std::map<_tstring, FILEINFO>& fileList,
        const _tstring& strDir,
        const std::vector<_tstring>& extList = {},
        int32_t depth = MAX_PATH,
        bool bIgnoreCase = true
    );

    //
    // @brief: 获取目录下子目录
    // @param: fileList     文件信息容器
    // @param: strDir          指定目录
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @ret: void
    static void GetDirList(
        std::vector<_tstring>& fileList,
        const _tstring& strDir,
        int32_t depth = MAX_PATH
    );

    //
    // @brief: 获取目录下文件路径
    // @param: fileList     文件信息容器
    // @param: strDir          指定目录
    // @param: depth        目录深度 如: 0:指定目录为根目录, 遍历0层子目录 
    // @ret: void
    static void GetDirList(
        std::map<_tstring, FILEINFO>& dirList,
        const _tstring& strDir,
        int32_t depth = MAX_PATH
    );

    //
    // @brief: 检查路径是否存在
    // @param: strPath      路径
    // @ret: 存在返回true
    static bool IsExist(const _tstring& strPath);

    //
    // @brief: 检查路径是否隐藏
    // @param: strPath      路径
    // @ret: 隐藏返回true
    static bool IsHidden(const _tstring& strPath);

    //
    // @brief: 检查路径是否是存档
    // @param: strPath      路径
    // @ret: 存档返回true
    static bool IsArchive(const _tstring& strPath);

    //
    // @brief: 检查路径是否是只读
    // @param: strPath      路径
    // @ret: 只读返回true
    static bool IsReadOnly(const _tstring& strPath);

    //
    // @brief: 检查路径是否是目录
    // @param: strPath      路径
    // @ret: 目录返回true
    static bool IsDirectory(const _tstring& strPath);

    //
    // @brief: 获取路径属性
    // @param: strPath      路径
    // @ret: 成功返回true
    static bool GetAttributes(const _tstring& strPath, DWORD& dwAttr);

    //
    // @brief: 设置路径属性
    // @param: strPath      路径
    // @ret: 成功返回true
    static bool SetAttributes(const _tstring& strPath, const DWORD& dwAttr);

    //
    // @brief: 获取文件大小
    // @param: strPath      路径
    // @ret: 文件大小
    static unsigned long long GetFileSize(const _tstring& strPath);

    //
    // @brief: 删除文件
    // @param: strPath      路径
    // @ret: 成功返回true
    static bool DeleteArchive(const _tstring& strPath);

    //
    // @brief: 删除目录(递归删除子目录及文件)
    // @param: strPath      路径
    // @ret: 成功返回true
    static bool DeleteDir(const _tstring& strPath);

    //
    // @brief: 创建目录(递归)
    // @param: strPath      路径
    // @ret: 成功返回true
    static bool CreateDir(const _tstring& strPath);
};

class CFileHelper
{
public:
    static bool GetAttributes(const _tstring& strPath, DWORD& dwAttr);
    static bool SetAttributes(const _tstring& strPath, const DWORD& dwAttr);

public:
    CFileHelper();
    CFileHelper(const CFileHelper&) = delete;
    CFileHelper(const _tstring& strPath, bool bReadonly = false);
    ~CFileHelper();

    bool Open(const _tstring& strPath, bool bCreateIfNoExist = true, bool bReadonly = false);
    void Close();
    bool IsOpen() const;
    bool GetSize(unsigned long long& ullSize) const;
    bool GetAttributes(DWORD& dwAttr) const;
    bool SetAttributes(const DWORD& dwAttr) const;
    LONGLONG GetPointer() const;
    bool SetPointer(LONGLONG llPos = 0, DWORD dwFlag = FILE_CURRENT);
    bool Read(LPVOID lpBuffer, DWORD dwSize, LONGLONG llPos = 0, LPDWORD lpBytesRead = nullptr, DWORD dwFlag = FILE_CURRENT);
    bool Write(LPCVOID lpBuffer, DWORD dwSize, LONGLONG llPos = 0, LPDWORD lpBytesWritten = nullptr, DWORD dwFlag = FILE_CURRENT);
    bool Clear();
    bool SetEnd(LONGLONG llPos);

private:
    HANDLE m_hFile;
    _tstring m_strFile;
};

CFileUtils.cpp

#include "CFileUtils.h"
#include <io.h>

_tstring CFileUtils::GetFileExtName(const _tstring& strfileName, bool bIncludeDot/* = false*/)
{
    _tstring strExtName = strfileName;
    size_t nExtPos = strExtName.find_last_of(_T('.'));
    if (_tstring::npos == nExtPos)
    {
        return _T("");
    }

    if (bIncludeDot)
    {
        strExtName.erase(0, nExtPos);
    }
    else
    {
        strExtName.erase(0, nExtPos + 1);
    }

    return strExtName;
}

void CFileUtils::GetFileList(
    std::vector<_tstring>& fileList, 
    const _tstring& strDir, 
    const std::vector<_tstring>& extList /* = {} */, 
    int32_t depth /*  = MAX_PATH */,
    bool bIgnoreCase/* = true*/
)
{
    //到达深度限制返回
    if (depth < 0)
    {
        return;
    }

    WIN32_FIND_DATA findData = { 0 };
    HANDLE hFindHandle = INVALID_HANDLE_VALUE;
    hFindHandle = FindFirstFile((strDir + _T("\\*.*")).c_str(), &findData);
    if (INVALID_HANDLE_VALUE == hFindHandle)
    {
        return;
    }

    do
    {
        _tstring strName = findData.cFileName;

        //非目录
        if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        {
            if (extList.empty())
            {
                fileList.emplace_back(strDir + _T("\\") + strName);
            }
            else
            {
                //获取扩展名
                _tstring strExtName = GetFileExtName(strName, false);

                //大小写比较区分
                if (bIgnoreCase)
                {
                    //进行扩展名过滤
                    for (auto& item : extList)
                    {
                        if (0 == _tcsicmp(item.c_str(), strExtName.c_str()))
                        {
                            fileList.emplace_back(strDir + _T("\\") + strName);
                        }
                    }
                }
                else
                {
                    //进行扩展名过滤
                    for (auto& item : extList)
                    {
                        if (item == strExtName)
                        {
                            fileList.emplace_back(strDir + _T("\\") + strName);
                        }
                    }
                }
            }
            continue;
        }

        //上一级目录与当前目录跳过
        if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
        {
            continue;
        }

        (void)GetFileList(fileList, strDir + _T("\\") + strName, extList, depth - 1);

    } while (::FindNextFile(hFindHandle, &findData));

    ::FindClose(hFindHandle);
}

void CFileUtils::GetFileList(
    std::set<_tstring>& fileList,
    const _tstring& strDir,
    const std::vector<_tstring>& extList/* = {}*/,
    int32_t depth/* = MAX_PATH*/,
    bool bIgnoreCase/* = true*/
)
{
    //到达深度限制返回
    if (depth < 0)
    {
        return;
    }

    WIN32_FIND_DATA findData = { 0 };
    HANDLE hFindHandle = INVALID_HANDLE_VALUE;
    hFindHandle = FindFirstFile((strDir + _T("\\*.*")).c_str(), &findData);
    if (INVALID_HANDLE_VALUE == hFindHandle)
    {
        return;
    }

    do
    {
        _tstring strName = findData.cFileName;

        //非目录
        if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        {
            if (extList.empty())
            {
                fileList.insert(strDir + _T("\\") + strName);
            }
            else
            {
                //获取扩展名
                _tstring strExtName = GetFileExtName(strName, false);

                //大小写比较区分
                if (bIgnoreCase)
                {
                    //进行扩展名过滤
                    for (auto& item : extList)
                    {
                        if (0 == _tcsicmp(item.c_str(), strExtName.c_str()))
                        {
                            fileList.insert(strDir + _T("\\") + strName);
                        }
                    }
                }
                else
                {
                    //进行扩展名过滤
                    for (auto& item : extList)
                    {
                        if (item == strExtName)
                        {
                            fileList.insert(strDir + _T("\\") + strName);
                        }
                    }
                }
            }
            continue;
        }

        //上一级目录与当前目录跳过
        if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
        {
            continue;
        }

        (void)GetFileList(fileList, strDir + _T("\\") + strName, extList, depth - 1);

    } while (::FindNextFile(hFindHandle, &findData));

    ::FindClose(hFindHandle);
}

void CFileUtils::GetFileList(
    std::map<_tstring, FILEINFO>& fileList,
    const _tstring& dir,
    const std::vector<_tstring>& extList /* = {} */,
    int32_t depth /*  = MAX_PATH */,
    bool bIgnoreCase/* = true*/
)
{
    //到达深度限制返回
    if (depth < 0)
    {
        return;
    }

    WIN32_FIND_DATA findData = { 0 };
    HANDLE hFindHandle = INVALID_HANDLE_VALUE;
    hFindHandle = FindFirstFile((dir + _T("\\*.*")).c_str(), &findData);
    if (INVALID_HANDLE_VALUE == hFindHandle)
    {
        return;
    }

    do
    {
        _tstring strName = findData.cFileName;

        //非目录
        if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        {
            FILEINFO info;
            info.m_fileName = findData.cFileName;
            info.m_fileSize = (unsigned long long)findData.nFileSizeHigh << 32 | findData.nFileSizeLow;
            info.m_fileDir = dir;
            info.m_filePath = dir + _T("\\") + strName;
            info.m_ftCreationTime = *(size_t*)&findData.ftCreationTime;
            info.m_ftLastAccessTime = *(size_t*)&findData.ftLastAccessTime;
            info.m_ftLastWriteTime = *(size_t*)&findData.ftLastWriteTime;
            info.m_fileAttributes = findData.dwFileAttributes;

            info.m_ftCreationTime = (info.m_ftCreationTime - 116444736000000000) / 10000000;
            info.m_ftLastAccessTime = (info.m_ftLastAccessTime - 116444736000000000) / 10000000;
            info.m_ftLastWriteTime = (info.m_ftLastWriteTime - 116444736000000000) / 10000000;

            if (extList.empty())
            {
                fileList.insert(std::make_pair(dir + _T("\\") + strName, info));
            }
            else
            {
                //获取扩展名
                _tstring strExtName = GetFileExtName(strName, false);

                //大小写比较区分
                if (bIgnoreCase)
                {
                    //进行扩展名过滤
                    for (const auto& item : extList)
                    {
                        if (0 == _tcsicmp(item.c_str(), strExtName.c_str()))
                        {
                            fileList.insert(std::make_pair(dir + _T("\\") + strName, info));
                        }
                    }
                }
                else
                {
                    //进行扩展名过滤
                    for (const auto& item : extList)
                    {
                        if (item == strExtName)
                        {
                            fileList.insert(std::make_pair(dir + _T("\\") + strName, info));
                        }
                    }
                }
            }
            continue;
        }

        //上一级目录与当前目录跳过
        if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
        {
            continue;
        }

        (void)GetFileList(fileList, dir + _T("\\") + strName, extList, depth - 1);

    } while (::FindNextFile(hFindHandle, &findData));

    ::FindClose(hFindHandle);
}

void CFileUtils::GetDirList(
    std::vector<_tstring>& fileList,
    const _tstring& strDir,
    int32_t depth/* = MAX_PATH*/
)
{
    //到达深度限制返回
    if (depth < 0)
    {
        return;
    }

    WIN32_FIND_DATA findData = { 0 };
    HANDLE hFindHandle = INVALID_HANDLE_VALUE;
    hFindHandle = FindFirstFile((strDir + _T("\\*.*")).c_str(), &findData);
    if (INVALID_HANDLE_VALUE == hFindHandle)
    {
        return;
    }

    do
    {
        _tstring strName = findData.cFileName;

        //上一级目录与当前目录跳过
        if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
        {
            continue;
        }

        //非目录
        if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        {
            continue;
        }

        fileList.emplace_back(strDir + _T("\\") + strName);
        (void)GetDirList(fileList, strDir + _T("\\") + strName, depth - 1);

    } while (::FindNextFile(hFindHandle, &findData));

    ::FindClose(hFindHandle);
}

void CFileUtils::GetDirList(
    std::map<_tstring, FILEINFO>& dirList,
    const _tstring& strDir,
    int32_t depth/* = MAX_PATH*/
)
{
    //到达深度限制返回
    if (depth < 0)
    {
        return;
    }

    WIN32_FIND_DATA findData = { 0 };
    HANDLE hFindHandle = INVALID_HANDLE_VALUE;
    hFindHandle = FindFirstFile((strDir + _T("\\*.*")).c_str(), &findData);
    if (INVALID_HANDLE_VALUE == hFindHandle)
    {
        return;
    }

    do
    {
        _tstring strName = findData.cFileName;

        //上一级目录与当前目录跳过
        if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
        {
            continue;
        }

        //非目录
        if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        {
            continue;
        }

        FILEINFO info;
        info.m_fileName = findData.cFileName;
        info.m_fileSize = (unsigned long long)findData.nFileSizeHigh << 32 | findData.nFileSizeLow;
        info.m_fileDir = strDir;
        info.m_filePath = strDir + _T("\\") + strName;
        info.m_ftCreationTime = *(size_t*)&findData.ftCreationTime;
        info.m_ftLastAccessTime = *(size_t*)&findData.ftLastAccessTime;
        info.m_ftLastWriteTime = *(size_t*)&findData.ftLastWriteTime;
        info.m_fileAttributes = findData.dwFileAttributes;

        info.m_ftCreationTime = (info.m_ftCreationTime - 116444736000000000) / 10000000;
        info.m_ftLastAccessTime = (info.m_ftLastAccessTime - 116444736000000000) / 10000000;
        info.m_ftLastWriteTime = (info.m_ftLastWriteTime - 116444736000000000) / 10000000;

        dirList.insert(std::make_pair(strDir + _T("\\") + strName, info));
        (void)GetDirList(dirList, strDir + _T("\\") + strName, depth - 1);

    } while (::FindNextFile(hFindHandle, &findData));

    ::FindClose(hFindHandle);
}

bool CFileUtils::IsExist(const _tstring& strPath)
{
    return 0 == _taccess_s(strPath.c_str(), 00);
}

bool CFileUtils::IsHidden(const _tstring& strPath)
{
    WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
    if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
    {
        return false;
    }

    return attr.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN;
}

bool CFileUtils::IsArchive(const _tstring& strPath)
{
    WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
    if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
    {
        return false;
    }

    return attr.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE;
}

bool CFileUtils::IsReadOnly(const _tstring& strPath)
{
    WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
    if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
    {
        return false;
    }

    return attr.dwFileAttributes & FILE_ATTRIBUTE_READONLY;
}

bool CFileUtils::IsDirectory(const _tstring& strPath)
{
    WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
    if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
    {
        return false;
    }

    return attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
}

bool CFileUtils::GetAttributes(const _tstring& strPath, DWORD& dwAttr)
{
    WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
    if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
    {
        return false;
    }

    dwAttr = attr.dwFileAttributes;
    return true;
}

bool CFileUtils::SetAttributes(const _tstring& strPath, const DWORD& dwAttr)
{
    return ::SetFileAttributes(strPath.c_str(), dwAttr);
}

unsigned long long CFileUtils::GetFileSize(const _tstring& strPath)
{
    unsigned long long ullSize = 0;
    WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
    if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
    {
        return 0;
    }

    ullSize = (unsigned long long)attr.nFileSizeHigh << 32 | attr.nFileSizeLow;

    return ullSize;
}

bool CFileUtils::DeleteArchive(const _tstring& strPath)
{
    bool bSuccess = false;

    if (strPath.empty())
    {
        return false;
    }

    bSuccess = ::DeleteFile(strPath.c_str());

    if (!bSuccess && ERROR_FILE_NOT_FOUND == ::GetLastError())
    {
        bSuccess = true;
    }

    return bSuccess;
}

bool CFileUtils::DeleteDir(const _tstring& strDir)
{
    WIN32_FIND_DATA findData = { 0 };
    HANDLE hFindHandle = INVALID_HANDLE_VALUE;

    if (strDir.empty())
    {
        return false;
    }

    hFindHandle = FindFirstFile((strDir + _T("\\*.*")).c_str(), &findData);
    if (INVALID_HANDLE_VALUE == hFindHandle)
    {
        return false;
    }

    do
    {
        _tstring strFilePath = strDir + _T("\\") + findData.cFileName;

        //上一级目录与当前目录跳过
        if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
        {
            continue;
        }

        if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //删除目录
        {
            DeleteDir(strFilePath);
            continue;
        }
        else    //删除文件
        {
            ::DeleteFile(strFilePath.c_str());
        }

    } while (::FindNextFile(hFindHandle, &findData));
    ::FindClose(hFindHandle);

    return ::RemoveDirectory(strDir.c_str());
}

bool CFileUtils::CreateDir(const _tstring& strPath)
{
    _tstring strDriver;              //驱动器号, 如 D:
    _tstring strSubPath = strPath;   //路径, 如 Test\1\2\3

    if (strPath.empty())
    {
        return false;
    }

    //获取盘符
    do
    {
        size_t nFindIndex = strPath.find_first_of(':');  //检查是否有驱动器号
        if (nFindIndex == _tstring::npos)
        {
            break;
        }

        strDriver = strPath.substr(0, nFindIndex + 1); //得到驱动器号, 如 D:
        nFindIndex = strPath.find(_T("\\"), nFindIndex);
        if (nFindIndex == _tstring::npos)
        {
            break;
        }

        strSubPath = strPath.substr(nFindIndex + 1); //得到路径, 如 Test\1\2\3
    } while (false);

    _tstring strDestDir;
    size_t nFindBegin = 0;
    size_t nFindIndex = 0;
    do
    {
        nFindIndex = strSubPath.find(_T("\\"), nFindBegin);
        if (nFindIndex != _tstring::npos)
        {
            strDestDir = strSubPath.substr(0, nFindIndex);
            nFindBegin = nFindIndex + 1;
        }
        else
        {
            strDestDir = strSubPath;
        }

        if (!strDriver.empty())
        {
            strDestDir = strDriver + _T("\\") + strDestDir;
        }

        if (!::CreateDirectory(strDestDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != ::GetLastError())
        {
            return false;
        }

    }while (nFindIndex != _tstring::npos);

    return true;
}

CFileHelper::CFileHelper()
    :
    m_hFile(INVALID_HANDLE_VALUE)
{

}

CFileHelper::CFileHelper(const _tstring& strPath, bool bReadonly/* = false*/)
{
    Open(strPath, true, bReadonly);
}

CFileHelper::~CFileHelper()
{
    Close();
}

bool CFileHelper::IsOpen() const
{
    return INVALID_HANDLE_VALUE != m_hFile;
}

bool CFileHelper::GetSize(unsigned long long& ullSize) const
{
    if (!IsOpen())
    {
        return false;
    }

    LARGE_INTEGER ullFileSize = { 0 };
    if (!::GetFileSizeEx(m_hFile, &ullFileSize))
    {
        return false;
    }

    ullSize = ullFileSize.QuadPart;
    return true;
}

bool CFileHelper::GetAttributes(const _tstring& strPath, DWORD& dwAttr)
{
    WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
    if (!::GetFileAttributesEx(strPath.c_str(), GetFileExInfoStandard, &attr))
    {
        return false;
    }

    dwAttr = attr.dwFileAttributes;
    return true;
}

bool CFileHelper::SetAttributes(const _tstring& strPath, const DWORD& dwAttr)
{
    return ::SetFileAttributes(strPath.c_str(), dwAttr);
}

bool CFileHelper::GetAttributes(DWORD& dwAttr) const
{
    if (!IsOpen())
    {
        return false;
    }

    return GetAttributes(m_strFile, dwAttr);
}

bool CFileHelper::SetAttributes(const DWORD& dwAttr) const
{
    if (!IsOpen())
    {
        return false;
    }

    return SetAttributes(m_strFile, dwAttr);
}

bool CFileHelper::Open(const _tstring& strPath, bool bCreateIfNoExist/* = false*/, bool bReadonly/* = false*/)
{
    if (strPath.empty())
    {
        return false;
    }

    //不重复打开相同文件
    if (m_strFile == strPath && IsOpen())
    {
        return true;
    }

    //关闭文件, 如果已经打开
    Close();

    m_strFile = strPath;
    DWORD dwOpenFlag = GENERIC_READ;
    if (!bReadonly)
    {
        dwOpenFlag |= GENERIC_WRITE;
    }

    m_hFile = CreateFile(m_strFile.c_str(),
        dwOpenFlag,
        FILE_SHARE_READ,
        NULL,
        bCreateIfNoExist ? OPEN_ALWAYS : OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (INVALID_HANDLE_VALUE == m_hFile)
    {
        return false;
    }

    return true;
}

void CFileHelper::Close()
{
    if (INVALID_HANDLE_VALUE != m_hFile)
    {
        ::CloseHandle(m_hFile);
        m_hFile = INVALID_HANDLE_VALUE;
    }
}

LONGLONG CFileHelper::GetPointer() const
{
    LARGE_INTEGER  liDistanceToMove = { 0 };
    LARGE_INTEGER  liNewFilePointer = { 0 };
    ::SetFilePointerEx(m_hFile, liDistanceToMove, &liNewFilePointer, FILE_CURRENT);

    return liNewFilePointer.QuadPart;
}

bool CFileHelper::SetPointer(LONGLONG llPos/* = 0*/, DWORD dwFlag/* = FILE_CURRENT*/)
{
    LARGE_INTEGER  liDistanceToMove = { 0 };

    if (!IsOpen())
    {
        return false;
    }

    liDistanceToMove.QuadPart = llPos;
    return ::SetFilePointerEx(m_hFile, liDistanceToMove, NULL, dwFlag);
}

bool CFileHelper::Read(LPVOID lpBuffer, DWORD dwSize, LONGLONG llPos/* = 0*/, LPDWORD lpBytesRead/* = nullptr*/, DWORD dwFlag/* = FILE_CURRENT*/)
{
    if (!IsOpen() || nullptr == lpBuffer)
    {
        return false;
    }

    LARGE_INTEGER  liDistanceToMove = { 0 };
    BOOL bResult = FALSE;
    liDistanceToMove.QuadPart = llPos;
    ::SetFilePointerEx(m_hFile, liDistanceToMove, NULL, dwFlag);
    DWORD dwBytesRead = 0;

    bResult = ::ReadFile(m_hFile, lpBuffer, dwSize, &dwBytesRead, NULL);
    if (nullptr != lpBytesRead)
    {
        *lpBytesRead = dwBytesRead;
    }

    return bResult;
}

bool CFileHelper::Write(LPCVOID lpBuffer, DWORD dwSize, LONGLONG llPos/* = 0*/, LPDWORD lpBytesWritten/* = nullptr*/, DWORD dwFlag/* = FILE_CURRENT*/)
{
    if (!IsOpen() || nullptr == lpBuffer)
    {
        return false;
    }

    LARGE_INTEGER  liDistanceToMove = { 0 };
    BOOL bResult = FALSE;
    liDistanceToMove.QuadPart = llPos;
    ::SetFilePointerEx(m_hFile, liDistanceToMove, NULL, dwFlag);

    DWORD dwBytesWritten = 0;
    bResult = ::WriteFile(m_hFile, lpBuffer, dwSize, &dwBytesWritten, NULL);

    if (nullptr != lpBytesWritten)
    {
        *lpBytesWritten = dwBytesWritten;
    }

    return bResult;
}

bool CFileHelper::Clear()
{
    if (!IsOpen())
    {
        return false;
    }

    LARGE_INTEGER  liDistanceToMove = { 0 };
    ::SetFilePointerEx(m_hFile, liDistanceToMove, NULL, FILE_BEGIN);
    return ::SetEndOfFile(m_hFile);
}

bool CFileHelper::SetEnd(LONGLONG llPos)
{
    if (!IsOpen())
    {
        return false;
    }

    LARGE_INTEGER  liDistanceToMove = { 0 };
    liDistanceToMove.QuadPart = llPos;
    ::SetFilePointerEx(m_hFile, liDistanceToMove, NULL, FILE_BEGIN);
    return ::SetEndOfFile(m_hFile);
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值