• 一个封装文件操作和目录操作的类


    经常在项目中遇到文件和目录操作。拷贝,删除,移动,最讨厌的可能就是枚举了。

    这里提供一个封装文件和目录的操作类。

    此类封装了一些高级的文件和目录操作。例如删除、建立、拷贝、移动、枚举文件和目录。

    所有的错误处理都内置了。并且用bool值类型来表示其成功与否。如果失败,可以调用GetErrorMessage

    函数得到CString类型的错误信息。

    用法:这个类只需要建立CDiskObject对象,然后调用它的成员函数即可。

    可以通过构造函数,传入一个CWnd指针用来调用 SetWindowText显示相关信息。

    //diskobject.h

    #define EF_ONLY_FILENAMES    0
    #define EF_FULLY_QUALIFIED    1

    class CDiskObject
    {
    public:
        // ctor(s)
        CDiskObject();
        CDiskObject( CWnd* feedbackWindow );

        // dtor
        ~CDiskObject();

        // - - -
        // Operations

        // Files

        BOOL FileExists( const CString& file );
        BOOL FileInformation( const CString& file, BY_HANDLE_FILE_INFORMATION &file_info);
        BOOL CreateFile( const CString& file );
        BOOL CopyFile( const CString& sourceFile, const CString& destDirectory );
        BOOL CopyFile( const CString& sourceFile, const CString& destDirectory, const CString& destFile );
        BOOL RemoveFile( const CString& sourceFile );
        BOOL RenameFile( const CString& sourceFile, const CString& destFile );
        BOOL MoveFile( const CString& sourceFile, const CString& destFile );

        BOOL CopyFiles( const CString& sourceDirectory, const CString& destDirectory );
        BOOL CopyFiles( CStringArray& files, const CString& destDirectory );

        // Directories

        BOOL DirectoryExists( const CString& file );

        BOOL CreateDirectory( const CString& directory );
        BOOL CopyDirectory( const CString& sourceDirectory, const CString& destDirectory );
        BOOL EmptyDirectory( const CString& directory );
        BOOL RemoveDirectory( const CString& directory );

        BOOL CopyDirectories( const CString& sourceDirectory, const CString& destDirectory );
        BOOL EmptyDirectories( const CString& directory );
        BOOL RemoveDirectories( const CString& directory );

        BOOL EnumFilesInDirectoryWithFilter( const CString& filter, const CString& sourceDirectory, CStringArray& files, int mode = EF_ONLY_FILENAMES );
        BOOL EnumAllDirectories( const CString& sourceDirectory, CStringArray& directories );
        BOOL EnumDirectories( const CString& sourceDirectory, CStringArray& directories );
        BOOL EnumFilesInDirectory( const CString& sourceDirectory, CStringArray& files, int mode = EF_ONLY_FILENAMES );
        BOOL EnumAllFiles( const CString& sourceDirectory, CStringArray& files );
        BOOL EnumAllFilesWithFilter( const CString& filter, const CString& sourceDirectory, CStringArray& files );

        // Error handling
        CString GetErrorMessage();   

    private:
        // Error handling
        CString m_errorMessage;

        void    ClearError();
        void    SetInternalErrorMessage();
        void    SetSystemErrorMessage( int error, const CString& elements = _T( "" ) );

        // Helpers

        CWnd*    m_feedbackWindow;
        void    QualifyPath( CString& str );
        void    QualifyFile( CString& str );
        CString GetFileName( const CString& str );
        CString GetDirectoryName( const CString& str );

    };

    //diskobject.cpp

    #include <tchar.h>
    #include "DiskObject.h"

    #pragma warning( disable : 4706 )

    #define Trigger( a)    if( m_feedbackWindow ) m_feedbackWindow->SetWindowText( a );

    ////////////////////////////////////////////////////////////////////
    // CDiskObject construction/destruction/initialization

    CDiskObject::CDiskObject()
    /* ============================================================
        Function :        CDiskObject::CDiskObject
        Description :    Constructor
        Access :        Public

        Return :        void
        Parameters :    none
        Usage :            Should normally be created on the stack.

       ============================================================*/
    {
        m_feedbackWindow = NULL;
    }

    CDiskObject::CDiskObject( CWnd* feedbackWindow )
    /* ============================================================
        Function :        CDiskObject::CDiskObject
        Description :    Constructor
        Access :        Public
        Return :        void
        Parameters :    CWnd* hwndFeedback    -    "CWnd" to feedback
                                                window

         Usage :            Should normally be created on the stack.

      ============================================================*/
    {
        m_feedbackWindow = feedbackWindow;
    }

    CDiskObject::~CDiskObject( )
    /* ============================================================
        Function :        CDiskObject::~CDiskObject
        Description :    Destructor
        Access :        Public
        Return :        void
        Parameters :    none

        Usage :            Should normally be created on the stack.

       ============================================================*/
    {
    }

    ////////////////////////////////////////////////////////////////////
    // CDiskObject operations
    //

    // File operations

    BOOL CDiskObject::CopyFiles( const CString& sourceDirectory,const CString& destDirectory )
    /* ============================================================
        Function :        CDiskObject::CopyFiles
        Description :    The member copies all files from
                        "sourceDirectory" to "destDirectory".
                        Subdirectories will not be copied.
        Access :        Public
        Return :        BOOL                    -    "TRUE" if OK.
                                                    "GetErrorMessage"
                                                    will return
                                                    errors.
        Parameters :    CString sourceDirectory    -    Copy from. If
                                                    empty, current.
                        CString destDirectory    -    Copy to. If
                                                    empty, current.
        Usage :            Call to copy the files from one directory to
                        another.

       ============================================================*/
    {
        ClearError( );
        CString source( sourceDirectory );
        CString dest( destDirectory );
        QualifyPath( source );
        QualifyPath( dest );

        // First, we enumerate all files
        CStringArray files;
        BOOL result = EnumFilesInDirectory( source, files );
        if( result )
        {
            // Create the destination directory, if necessary
            if( ( result = CreateDirectory( dest ) ) )
            {
                int max = files.GetSize( );
                for( int t = 0 ; t < max ; t++ )
                {
                    // Copy the files
                    CString file;
                    file = files[ t ];
                    Trigger( file );
                    if( !( result = ::CopyFile( source + file, dest + file, FALSE ) ) )
                    {
                        // Set error message
                        SetSystemErrorMessage( ::GetLastError( ),
                                                source +
                                                file +
                                                _T( " -> " ) +
                                                dest +
                                                file );
                        t = max;
                    }
                }
            }
        }

        return result;
    }

    BOOL CDiskObject::CopyFiles( CStringArray& files,const CString& destDirectory )
    /* ============================================================
        Function :        CDiskObject::CopyFiles
        Description :    The function copies the files in the
                        "CStringArray" "files" to the directory
                        "destDirectory". Existing files will be
                        overwritten. The destination will be
                        created if it doesn't already exist.
        Access :        Public
        Return :        BOOL                    -    "TRUE" if OK.
                                                    "GetErrorMessage"
                                                    will return
                                                    errors.
        Parameters :    CStringArray& files        -    a string array
                                                    with the files
                                                    to copy
                        CString destDirectory    -    destination
        Usage :            Copy a list of files to a directory.

       ============================================================*/
    {
        ClearError( );
        CString dest( destDirectory );

        BOOL result = TRUE;
        if( files.GetSize( ) )
        {
            QualifyPath( dest );

            // Create destination, if necessary
            if( ( result = CreateDirectory( dest ) ) )
            {
                int max = files.GetSize( );
                for( int t = 0 ; t < max ; t++ )
                {
                    // Loop and copy the files
                    CString file;
                    file = files[ t ];
                    if( file.GetLength( ) )
                    {
                        Trigger( file );
                        QualifyFile( file );

                        // Create destination filename
                        CString to = dest + GetFileName( file );
                        if( !( result = ::CopyFile( file, to, FALSE ) ) )
                        {
                            // Set error message
                            SetSystemErrorMessage( ::GetLastError( ),
                                                    file +
                                                    _T( " -> " ) +
                                                    dest +
                                                    file );
                            t = max;
                        }
                    }
                }
            }
        }
        else
        {
            SetInternalErrorMessage( );
            result =  FALSE;
        }

        return result;
    }

    BOOL CDiskObject::CopyFile( const CString& sourceFile,const CString& destDirectory )
    /* ============================================================
        Function :        CDiskObject::CopyFile
        Description :    Will copy "sourceFile" to "destDirectory".
                        An existing file will be overwritten. The
                        directory will be created if it doesn't exist.
        Access :        Public
        Return :        BOOL                    -    "TRUE" if OK.
                                                    "GetErrorMessage"
                                                    will contain
                                                    errors
        Parameters :    CString sourceFile        -    file to copy
                        CString destDirectory    -    destination
        Usage :            Call to copy a file to a directory.

       ============================================================*/
    {
        ClearError( );
        CString source( sourceFile );
        CString dest( destDirectory );

        BOOL result = TRUE;
        if( sourceFile.GetLength( ) )
        {
            QualifyFile( source );
            QualifyPath( dest );

            // Creating destDirectory if necessary.
            if( ( result = CreateDirectory( dest ) ) )
            {
                CString filePart = GetFileName( source );
                // Copy the file
                Trigger( filePart );
                if( !( result = ::CopyFile( source, dest + filePart, FALSE ) ) )
                    SetSystemErrorMessage( ::GetLastError( ), source );
            }
        }
        else
        {
            SetInternalErrorMessage( );
            result = FALSE;
        }

        return result;
    }

    BOOL CDiskObject::CopyFile( const CString& sourceFile,const CString& destDirectory, const CString& destFile )
    /* ============================================================
        Function :        CDiskObject::CopyFile
        Description :    Will copy "sourceFile" to "destDirectory"
                        with the new name "destFile".
                        An existing file will be overwritten. The
                        directory will be created if it doesn't exist.
        Access :        Public
        Return :        BOOL                    -    "TRUE" if OK.
                                                    "GetErrorMessage"
                                                    will contain
                                                    errors
        Parameters :    CString sourceFile        -    file to copy
                        CString destDirectory    -    destination
                        CString destFile        -    destination file name
                                                    (in "destDirectory")
        Usage :            Call to copy a file to a directory.

       ============================================================*/
    {
        ClearError( );
        CString source( sourceFile );
        CString destDir( destDirectory );
        CString dest( destFile );

        BOOL result = TRUE;
        if( sourceFile.GetLength( ) )
        {
            QualifyFile( source );
            QualifyFile( dest );
            QualifyPath( destDir );

            // Creating destDirectory if necessary.
            if( ( result = CreateDirectory( destDir ) ) )
            {
                // Copy the file
                Trigger( dest );
                if( !( result = ::CopyFile( source, dest, FALSE ) ) )
                    SetSystemErrorMessage( ::GetLastError( ), source );
            }
        }
        else
        {
            SetInternalErrorMessage( );
            result = FALSE;
        }

        return result;
    }

    BOOL CDiskObject::RemoveFile( const CString& sourceFile )
    /* ============================================================
        Function :        CDiskObject::RemoveFile
        Description :    Will remove "sourceFile".
        Access :        Public
        Return :        BOOL                        -    "TRUE" if
                                                        removed ok
        Parameters :    const CString& sourceFile    -    File to
                                                        remove
        Usage :            Call to delete a file. Added for reasons
                        of symmetry.

       ============================================================*/
    {
        ClearError( );
        CString source( sourceFile );

        BOOL result = TRUE;
        if( sourceFile.GetLength( ) )
        {
            QualifyFile( source );

            if( !( result = ::DeleteFile( source ) ) )
                SetSystemErrorMessage( ::GetLastError( ), source );
        }
        else
        {
            SetInternalErrorMessage( );
            result = FALSE;
        }

        return result;
    }

    ////////////////////////////////////////
    // Directory operations
    //

    BOOL CDiskObject::DirectoryExists( const CString& directory )
    /* ============================================================
        Function :        CDiskObject::DirectoryExists
        Description :    Returns "TRUE" if the directory "directory"
                        exists
        Access :        Public
        Return :        BOOL                -    "TRUE" if found
        Parameters :    CString directory    -    directory to check

        Usage :            Call to check for directory existence.

       ============================================================*/
    {
        ClearError( );

        BOOL result = FALSE;

        if( directory.GetLength( ) )
        {
            CString indir( directory );
            QualifyPath( indir );

            TCHAR buff[ _MAX_PATH ];
            ::GetCurrentDirectory(_MAX_PATH, buff );

            if( ::SetCurrentDirectory( indir ) )
                result = TRUE;

            ::SetCurrentDirectory( buff );

        }
        else
        {
            SetInternalErrorMessage( );
        }

        return result;
    }

    BOOL CDiskObject::CreateDirectory( const CString& directory )
    /* ============================================================
        Function :        CDiskObject::CreateDirectory
        Description :    Will recursively create the directory
                        "directory".
        Access :        Public

        Return :        BOOL                -    "TRUE" if OK.
                                                "GetErrorMessage"
                                                will get an
                                                error string if
                                                "FALSE"
        Parameters :    CString directory    -    directory to
                                                create

        Usage :            Call to create a directory chain.

       ============================================================*/
    {
        ClearError( );

        BOOL result = TRUE;
        CString indir( directory );
        if( indir.GetLength( ) )
        {
            QualifyPath( indir );

            _TCHAR drive[ _MAX_PATH ];
            _TCHAR dir[ _MAX_DIR ];
            _TCHAR fname[ _MAX_FNAME ];
            _TCHAR ext[ _MAX_EXT ];

            // Split directory into parts
            _tsplitpath( indir, drive, dir, fname, ext );

            TCHAR currentDirectory[ _MAX_PATH ];
            ::GetCurrentDirectory( _MAX_PATH, currentDirectory );

            CStringArray directories;
            CString parts = dir;

            if( parts.GetLength( ) > 2 )
            {
                if( parts.Left( 2 ) == _T( "\\\\" ) )
                {
                    // We have an UNC name
                    CString strComputer;
                    parts = parts.Right( parts.GetLength( ) - 2 );
                    int findDir = parts.Find( _TCHAR( '\\' ) );
                    if( findDir!=-1)
                    {
                        strComputer = _T( "\\\\" ) + parts.Left( findDir );
                        parts = parts.Right( parts.GetLength( ) - ( findDir + 1 ) );
                    }
                    _tcscpy( drive, strComputer );
                }
            }

            CString strRoot( drive );

            // Strip leading \'s
            while( parts.GetLength( ) && parts[0] == _TCHAR( '\\' ) )
                parts = parts.Right( parts.GetLength( ) - 1 );

            // Cut into separate directories
            int find = parts.Find( _TCHAR( '\\' ) );
            while( find != -1 )
            {
                directories.Add( parts.Left( find ) );
                parts = parts.Right( parts.GetLength( ) - ( find + 1 ) );
                find = parts.Find( _TCHAR( '\\' ) );
            }

            if( parts.GetLength( ) )
                directories.Add( parts );

            if( fname )
                directories.Add( fname );

            // Loop directories one-by-one, creating as necessary
            int max = directories.GetSize( );
            CString strCurrentDirectory( strRoot );

            for( int t = 0 ; t < max ; t++ )
            {
                strCurrentDirectory += _TCHAR( '\\' ) + directories[ t ];
                Trigger( strCurrentDirectory );
                if( !( result = ::SetCurrentDirectory( strCurrentDirectory ) ) )
                {
                    if( !( result = ::CreateDirectory( strCurrentDirectory, NULL ) ) )
                    {
                        SetSystemErrorMessage( ::GetLastError( ), strCurrentDirectory );
                        t = max;
                    }
                }
            }

            ::SetCurrentDirectory( currentDirectory );

        }
        else
        {
            SetInternalErrorMessage( );
            result = FALSE;
        }
        return result;
    }

    BOOL CDiskObject::EmptyDirectory( const CString& directory )
    /* ============================================================
        Function :        CDiskObject::EmptyDirectory
        Description :    Will delete all files in directory.
        Access :        Public

        Return :        BOOL                -    "TRUE" if OK.
                                                "GetErrorMessage" will
                                                get an error
                                                string if "FALSE"
        Parameters :    CString directory    -    the directory to
                                                empty.

        Usage :            Call to empty a directory.

       ============================================================*/
    {
        ClearError( );
        CString indir( directory );
        QualifyPath( indir );

        // Enumerate all files
        CStringArray files;
        BOOL result = EnumFilesInDirectory( indir, files );
        if( result )
        {
            int max = files.GetSize( );
            for( int t = 0 ; t < max ; t++ )
            {
                // Loop and delete
                CString file = files[ t ];
                Trigger( file );
                if( !( result = ::DeleteFile( indir + file ) ) )
                {
                    SetSystemErrorMessage( ::GetLastError( ), indir + file );
                    t = max;
                }
            }
        }

        return result;
    }

    BOOL CDiskObject::RemoveDirectory( const CString& directory )
    /* ============================================================
        Function :        CDiskObject::RemoveDirectory
        Description :    Will remove the directory "directory", even
                        if not empty. Will not remove
                        subdirectories.
        Access :        Public
        Return :        BOOL                -    "TRUE" if OK.
                                                "GetErrorMessage"
                                                will get an error
                                                string if "FALSE"
        Parameters :    CString directory    -    directory to
                                                remove.

        Usage :            Call to remove a directory.

       ============================================================*/
    {
        ClearError( );

        BOOL result = TRUE;
        CString indir( directory );
        if( indir.GetLength( ) )
        {
            QualifyPath( indir );

            // Wipe and remove directory
            if( ( result = EmptyDirectory( indir ) ) )
            {
                Trigger( indir );
                if( !( result = ::RemoveDirectory( indir ) ) )
                    SetSystemErrorMessage( ::GetLastError( ), indir );
            }
        }
        else
        {
            // Small sanity check, we can't
            // delete the current directory.
            SetInternalErrorMessage( );
            result = FALSE;
        }

        return result;
    }

    BOOL CDiskObject::RemoveDirectories( const CString& directory )
    /* ============================================================
        Function :        CDiskObject::RemoveDirectories
        Description :    Will remove the directory "directory", even
                        if not empty. Will remove subdirectories.
        Access :        Public

        Return :        BOOL                -    "TRUE" if OK.
                                                "GetErrorMessage"
                                                will get an error
                                                string if "FALSE"
        Parameters :    CString directory    -    root directory to
                                                remove.

        Usage :            Call to remove a directory tree.

       ============================================================*/
    {
        ClearError( );

        BOOL result = TRUE;

        CString indir( directory );
        if( indir.GetLength( ) )
        {
            QualifyPath( indir );

            CStringArray directories;

            // Get all directories
            ;
            if( ( result = EnumAllDirectories( indir, directories ) ) )
            {
                // Loop and remove
                int max = directories.GetSize( );
                for( int t = max - 1; t >= 0 ; t-- )
                    if( !( result = RemoveDirectory( directories[ t ] ) ) )
                        t = -1;
                if( result )
                    result = RemoveDirectory( indir );
            }
        }
        else
        {
            // Small sanity check, we can't
            // delete the current directory.
            SetInternalErrorMessage( );
            result = FALSE;
        }

        return result;
    }

    BOOL CDiskObject::EmptyDirectories( const CString& directory )
    /* ============================================================
        Function :        CDiskObject::EmptyDirectories
        Description :    Will delete all files in "directory". Will
                        also empty subdirectories.
        Access :        Public
        Return :        BOOL                -    "TRUE" if OK.
                                                "GetErrorMessage"
                                                will get an error
                                                string if "FALSE"
        Parameters :    CString directory    -    the root directory
                                                to empty.

        Usage :            Call to empty a directory tree.

       ============================================================*/
    {
        ClearError( );

        CString indir( directory );

        QualifyPath( indir );
        CStringArray directories;

        // Get all directories
        BOOL result = EnumAllDirectories( indir, directories );
        if( result )
        {
            int max = directories.GetSize( );
            // Loop and empty
            for( int t = max - 1 ; t >= 0 ; t-- )
                if( !( result = EmptyDirectory( directories[ t ] ) ) )
                    t = -1;

            if( result )
                result = EmptyDirectory( indir );
        }

        return result;
    }

    BOOL CDiskObject::CopyDirectory( const CString& sourceDirectory,const CString& destDirectory )
    /* ============================================================
        Function :        CDiskObject::CopyDirectory
        Description :    Copies all the files from "sourceDirectory"
                        to "destDirectory". Existing files will be
                        overwritten. "destDirectory" will be created
                        if necessary. Subdirectories will not be
                        copied.
        Access :        Public
        Return :        BOOL                    -    "TRUE" if OK.
                                                    "GetErrorMessage"
                                                    will get an error
                                                    string if "FALSE"
        Parameters :    CString sourceDirectory    -    copy from.
                        CString destDirectory    -    copy to.

        Usage :            Call to copy a directory to another
                        directory.

       ============================================================*/
    {
        ClearError( );
        CString source( sourceDirectory );
        CString dest( destDirectory );
        QualifyPath( source );
        QualifyPath( dest );

        Trigger( dest );

        // We don't care if this fails - CopyFiles will
        // return an error in that case.
        ::CreateDirectory( dest, NULL );

        return CopyFiles( source, dest );

    }

    BOOL CDiskObject::CopyDirectories( const CString& sourceDirectory,const CString& destDirectory )
    /* ============================================================
        Function :        CDiskObject::CopyDirectories
        Description :    Copies all the files and subdirectories
                        from "sourceDirectory" to "destDirectory",
                        keeping the directory structure. Existing
                        files will be overwritten. "destDirectory"
                        and subdirectories will be created if
                        necessary.
        Access :        Public

        Return :        BOOL                    -    "TRUE" if OK.
                                                    "GetErrorMessage"
                                                    will get an
                                                    error string
                                                    if "FALSE"
        Parameters :    CString sourceDirectory    -    copy from.
                        CString destDirectory    -    copy to.

        Usage :            Call to copy a directory tree to a new
                        directory tree.

       ============================================================*/
    {
        ClearError( );

        CString source( sourceDirectory );
        CString dest( destDirectory );
        QualifyPath( source );
        QualifyPath( dest );

        // Enumerate all directories and files below sourceDirectory
        CStringArray directories;
        directories.Add( source );

        BOOL result = EnumAllDirectories( source, directories );
        if( result )
        {
            // Create and copy directories
            int max = directories.GetSize( );
            for( int t = 0 ; t < max ; t++ )
            {
                // Create names and copy
                CString from = directories[ t ];
                CString part = from.Right( from.GetLength( ) - source.GetLength( ) );
                CString to = dest + part;

                if( !( result = CopyFiles( from, to ) ) )
                    t = max;
            }
        }

        return result;
    }

    ////////////////////////////////////////
    // File-oriented operations
    //

    BOOL CDiskObject::FileExists( const CString& file )
    /* ============================================================
        Function :        CDiskObject::FileExists
        Description :    Returns "TRUE" if the file file exists
        Access :        Public
        Return :        BOOL            -    "TRUE" if found
        Parameters :    CString file    -    file to check

        Usage :            Call to check for file existence.

       ============================================================*/
    {
        ClearError( );

        BOOL result = TRUE;

        if( file.GetLength( ) )
        {
            CString infile( file );
            QualifyFile( infile );
            HANDLE filehandle = ::CreateFile(
                                    infile,
                                    GENERIC_READ,
                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
                                    NULL,
                                    OPEN_EXISTING,
                                    FILE_ATTRIBUTE_NORMAL,
                                    NULL
                                );

            if( filehandle == INVALID_HANDLE_VALUE )
                result = FALSE;
            else
                CloseHandle( filehandle );
        }
        else
        {
            SetInternalErrorMessage( );
            result = FALSE;
        }

        return result;
    }

    BOOL CDiskObject::FileInformation( const CString& file, BY_HANDLE_FILE_INFORMATION &file_info )
    /* ============================================================
        Function :        CDiskObject::FileInformation
        Description :    Returns "TRUE" if the file file exists
                        At this time file_info is filled out
        Access :        Public

        Return :        BOOL                                    -    "TRUE" if found
        Parameters :    CString file                            -    file to check
                        BY_HANDLE_FILE_INFORMATION &file_info    -    info filled out

        Usage :            Call to check for file existence and if there
                        return data about that file.

       ============================================================*/
    {
        ClearError( );

        BOOL result = TRUE;

        if( file.GetLength( ) )
        {
            CString infile( file );
            QualifyFile( infile );
            HANDLE filehandle = ::CreateFile(infile,
                                                GENERIC_READ,
                                                FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                NULL,
                                                OPEN_EXISTING,
                                                FILE_ATTRIBUTE_NORMAL,
                                                NULL);

            if( filehandle == INVALID_HANDLE_VALUE )
                result = FALSE;
            else
            {
                BY_HANDLE_FILE_INFORMATION file_info_local;
                if (GetFileInformationByHandle( filehandle, &file_info_local ))
                {
                    memcpy(&file_info, &file_info_local, sizeof(file_info_local));
                }
                else
                {
                    result = FALSE;
                    SetInternalErrorMessage( );
                }
                CloseHandle( filehandle );
            }
        }
        else
        {
            SetInternalErrorMessage( );
            result = FALSE;
        }

        return result;

    }

    BOOL CDiskObject::CreateFile( const CString& file )
    /* ============================================================
        Function :        CDiskObject::CreateFile
        Description :    Creates the file "file", as well as the
                        directories necessary
        Access :        Public

        Return :        BOOL            -    "TRUE" if OK
        Parameters :    CString file    -    file to create

        Usage :            Call to create a file.

       ============================================================*/
    {
        ClearError( );

        BOOL result = TRUE;

        if( file.GetLength( ) )
        {

            CString infile( file );
            QualifyFile( infile );

            // Split into directory and file
            CString directory = GetDirectoryName( infile );
            CString filename = GetFileName( infile );

            if( ( result = CreateDirectory( directory ) ) )
            {
                Trigger( file );
                HANDLE filehandle = ::CreateFile(
                                        infile,
                                        GENERIC_WRITE,
                                        0,
                                        NULL,
                                        CREATE_ALWAYS,
                                        FILE_ATTRIBUTE_NORMAL,
                                        NULL
                                    );

                if( filehandle == INVALID_HANDLE_VALUE )
                    result = FALSE;
                else
                    CloseHandle( filehandle );
            }
        }
        else
        {
            SetInternalErrorMessage( );
            result = FALSE;
        }

        return result;
    }

    BOOL CDiskObject::MoveFile( const CString& sourceFile, const CString& destFile )
    /* ============================================================
        Function :        CDiskObject::MoveFile
        Description :    Move the file "sourceFile" to "destFile".
                        Creates the destination directory if
                        necessary

        Access :        Public

        Return :        BOOL                        - "TRUE" if renamed OK
        Parameters :    const CString& sourceFile    - File to move
                        const CString& desFile        - New name/location

        Usage :            Call to move a file.

       ============================================================*/
    {

        ClearError( );

        BOOL result = FALSE;

        if( sourceFile.GetLength() && destFile.GetLength() )
        {
            CString insourcefile( sourceFile );
            QualifyFile( insourcefile );
            CString indestdir = GetDirectoryName( destFile );
            CString indestfilename = GetFileName( destFile );

            if( CopyFile( insourcefile, indestdir, indestfilename ) )
            {
                result = RemoveFile( sourceFile );
            }

        }

        return result;

    }

    BOOL CDiskObject::RenameFile( const CString& sourceFile, const CString& destFile )
    /* ============================================================
        Function :        CDiskObject::RenameFile
        Description :    Renames the file "sourceFile" to "destFile".
                        "destFile" is assumed to be a filename rather
                        than a fully qualified path.

        Access :        Public

        Return :        BOOL                        - "TRUE" if renamed OK
        Parameters :    const CString& sourceFile    - file to rename
                        const CString& desFile        - New name

        Usage :            Call to rename a file.

       ============================================================*/
    {

        ClearError( );

        BOOL result = FALSE;

        if( sourceFile.GetLength() && destFile.GetLength() )
        {
            CString insourcefile( sourceFile );
            QualifyFile( insourcefile );
            CString insourcedir = GetDirectoryName( insourcefile );
            if( CopyFile( sourceFile, insourcedir, destFile ) )
            {
                result = RemoveFile( sourceFile );
            }
        }

        return result;

    }

    ////////////////////////////////////////
    // Helpers
    //

    BOOL CDiskObject::EnumFilesInDirectory( const CString& sourceDirectory, CStringArray& files, int mode )
    /* ============================================================
        Function :        CDiskObject::EnumFilesInDirectory
        Description :    Enumerates all files in directory
                        "sourceDirectory", and adds them to the
                        "CStringArray" "files". Will not add
                        subdirectories
        Access :        Public

        Return :        BOOL                    -    "TRUE" if OK.
                                                    "GetErrorMessage"
                                                    will contain errors
        Parameters :    CString sourceDirectory    -    The directory to
                                                    enumerate
                        CStringArray& files        -    The resulting files
        Usage :            Call to get a list of files in a directory.

       ============================================================*/
    {
        return EnumFilesInDirectoryWithFilter( _T( "*.*" ), sourceDirectory, files, mode );
    }

    BOOL CDiskObject::EnumFilesInDirectoryWithFilter( const CString& strFilter,const CString& sourceDirectory, CStringArray& files, int mode )
    /* ============================================================
        Function :        CDiskObject::EnumFilesInDirectoryWithFilter
        Description :    Enumerates all files matching "strFilter" in
                        the directory "sourceDirectory", and adds
                        them to the "CStringArray" "files". Will not
                        add subdirectories.
        Access :        Public
        Return :        BOOL                    -    "TRUE" if OK.
                                                    "GetErrorMessage"
                                                    will contain errors
        Parameters :    CString strFilter        -    the file name filter
                        CString sourceDirectory    -    source directory
                        CStringArray& files        -    output array
        Usage :            Call to get a filtered list of files from
                        a directory.

       ============================================================*/
    {

        ClearError( );
        CString source( sourceDirectory );
        QualifyPath( source );
        CString sourceFiles( source + strFilter );
        BOOL result = TRUE;
        WIN32_FIND_DATA ff;

        HANDLE findhandle = FindFirstFile( sourceFiles, &ff );
        if( findhandle != INVALID_HANDLE_VALUE )
        {
            BOOL res = TRUE;
            while( res )
            {
                // We only want files
                if( !( ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
                {
                    BOOL    added = FALSE;
                    CString file;
                    file = ff.cFileName;

                    if( mode == EF_FULLY_QUALIFIED )
                        file = sourceDirectory + file;

                    // Return the array alphabetically ordered
                    for( int i = 0; i < files.GetSize(); i++ )
                    {
                        if ( files.GetAt( i ) > file )
                        {
                            files.InsertAt( i, file );
                            added = TRUE;
                            break;
                        }
                    }
                    if ( !added )
                    {
                        files.Add( file );
                    }

                    Trigger( file );
                }

                res = FindNextFile( findhandle, &ff );
            }

            FindClose( findhandle );
        }
        else
        {
            // Set error message
            SetSystemErrorMessage( ::GetLastError( ), sourceFiles );
            result = FALSE;
        }

        return result;

    }
    BOOL CDiskObject::EnumAllDirectories( const CString& sourceDirectory, CStringArray& directories )
    /* ============================================================
        Function :        CDiskObject::EnumAllDirectories
        Description :    Enumerates all directories recursively in
                        directory "sourceDirectory", and adds them
                        to the "CStringArray" "directories". Each entry
                        will be a fully qualified name
        Access :        Public

        Return :        BOOL                        -    "TRUE" if OK.
                                                        "GetErrorMessage"
                                                        will contain errors
        Parameters :    CString sourceDirectory        -    start directory
                        CStringArray& directories    -    "CStringArray" to be
                                                        filled with the
                                                        directory names.

        Usage :            Call to get the directory names in a
                        directory tree.

       ============================================================*/
    {
        ClearError( );

        CString source( sourceDirectory );
        QualifyPath( source );
        CString sourceFiles( source + _T( "*.*" ) );
        BOOL result = TRUE;
        WIN32_FIND_DATA ff;

        HANDLE findhandle = FindFirstFile( sourceFiles, &ff );
        if( findhandle != INVALID_HANDLE_VALUE)
        {

            BOOL res = TRUE;
            while( res)
            {
                // We only want directories
                if( ( ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) && _tcscmp( ff.cFileName, _T( "." ) ) && _tcscmp( ff.cFileName, _T( ".." ) ) )
                {
                    CString directory( source + ff.cFileName );
                    directories.Add( directory + _TCHAR( '\\' ) );
                    Trigger( ff.cFileName );
                    if( !( result = EnumAllDirectories( directory, directories ) ) )
                        res = FALSE;
                }

                if( res )
                    res = FindNextFile( findhandle, &ff );
                else
                    result = FALSE;
            }

            FindClose( findhandle );
        }
        else
        {
            // Set error message
            SetSystemErrorMessage( ::GetLastError( ), sourceFiles );
            result = FALSE;
        }

        return result;
    }
    BOOL CDiskObject::EnumDirectories( const CString& sourceDirectory, CStringArray& directories )
    /* ============================================================
        Function :        CDiskObject::EnumDirectories
        Description :    Enumerates all directories in directory
                        "sourceDirectory", and adds them to the
                        "CStringArray" "directories". Each entry will
                        be a fully qualified name
        Access :        Public

        Return :        BOOL                        -    "TRUE" if OK.
                                                        "GetErrorMessage"
                                                        will contain errors
        Parameters :    CString sourceDirectory        -    start directory
                        CStringArray& directories    -    "CStringArray" to be
                                                        filled with the
                                                        directory names.

        Usage :            Call to get a list of directories in a
                        directory tree.

       ============================================================*/
    {
        ClearError( );

        CString source( sourceDirectory );
        QualifyPath( source );
        CString sourceFiles( source + _T( "*.*" ) );
        BOOL result = TRUE;
        WIN32_FIND_DATA ff;

        HANDLE findhandle = FindFirstFile( sourceFiles, &ff );
        if( findhandle != INVALID_HANDLE_VALUE)
        {

            BOOL res = TRUE;
            while( res)
            {
                // We only want directories
                if( ( ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) && _tcscmp( ff.cFileName, _T( "." ) ) && _tcscmp( ff.cFileName, _T( ".." ) ) )
                {
                    directories.Add( ff.cFileName );
                    Trigger( ff.cFileName );
                }

                if( res )
                    res = FindNextFile( findhandle, &ff );
                else
                    result = FALSE;
            }

            FindClose( findhandle );
        }
        else
        {
            // Set error message
            SetSystemErrorMessage( ::GetLastError( ), sourceFiles );
            result = FALSE;
        }

        return result;
    }
    BOOL CDiskObject::EnumAllFiles( const CString& sourceDirectory, CStringArray& files )
    /* ============================================================
        Function :        CDiskObject::EnumAllFiles
        Description :    Returns, recursively, the fully qualified
                        names of all files found under
                        "sourceDirectory".
        Access :        Public

        Return :        BOOL                    -    "TRUE" if OK.
        Parameters :    CString sourceDirectory    -    Root dir   
                        CStringArray& files        -    output list
                                                    of all files
                                                    found

        Usage :            Call to get the names of all files in a
                        directory tree.

       ============================================================*/
    {
        return EnumAllFilesWithFilter( _T( "*.*" ), sourceDirectory, files );
    }

    BOOL CDiskObject::EnumAllFilesWithFilter( const CString& filter,const CString& sourceDirectory, CStringArray& files )
    /* ============================================================
        Function :        CDiskObject::EnumAllFiles
        Description :    Returns, recursively, the fully qualified
                        names of all files matching the filter
                        found under "sourceDirectory".
        Access :        Public

        Return :        BOOL                    -    "TRUE" if OK.
        Parameters :    CString filter            -    Filter for files
                                                    to find
                        CString sourceDirectory    -    Root dir   
                        CStringArray& files        -    output list
                                                    of all files
                                                    found

        Usage :            Call to get a filtered list of all files in
                        a directory tree.

       ============================================================*/
    {
        CStringArray dirs;
        BOOL result = EnumAllDirectories( sourceDirectory, dirs );
        dirs.Add(sourceDirectory);
        if( result )
        {
            int max1 = dirs.GetSize( );
            for( int t = 0 ; t < max1 ; t++ )
            {
                CString dir = dirs[ t ];
                QualifyPath( dir );
                CStringArray dirfiles;
                if( EnumFilesInDirectoryWithFilter( filter, dir, dirfiles, EF_FULLY_QUALIFIED ) )
                {
                    int max2 = dirfiles.GetSize( );
                    for( int i = 0 ; i < max2 ; i++ )
                    {
                        CString file = dirfiles[ i ];
                        Trigger( file );
                        files.Add( file );
                    }
                }
            }
        }

        return result;
    }

    ////////////////////////////////////////
    // Error handling

    CString CDiskObject::GetErrorMessage( )
    /* ============================================================
        Function :        CDiskObject::GetErrorMessage
        Description :    Will return the current error message for
                        the "CDiskObject".
        Access :        Public
        Return :        CString    -    current error message.
        Parameters :    none

        Usage :            Call to get the error message.

       ============================================================*/
    {
        return m_errorMessage;
    }

    // Private methods

    void CDiskObject::ClearError( )
    /* ============================================================
        Function :        CDiskObject::ClearError
        Description :    Clears the internal error message string
        Access :        Private
        Return :        void
        Parameters :    none

        Usage :            Call to clear the internal error message.

       ============================================================*/
    {
        m_errorMessage = _T( "" );
    }

    void CDiskObject::SetSystemErrorMessage( int error,const CString& elements)
    /* ============================================================
        Function :        CDiskObject::SetSystemErrorMessage
        Description :    Sets the error message string with the
                        system error message as gotten from
                        "GetLastError". "elements" will be appended.
        Access :        Private

        Return :        void
        Parameters :    int error            -    error number from
                                                "GetLastError"
                        CString elements    -    files or directories
                                                to add to the message
        Usage :            Call to set the error message.

       ============================================================*/
    {
        LPVOID msgBuff;

        // Format error message from system
        ::FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
            NULL,
            error,
            MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
            ( LPTSTR ) &msgBuff,
            0,
            NULL
        );

        // Create the error string
        m_errorMessage = CString( ( LPTSTR ) msgBuff );
        m_errorMessage.TrimLeft( );
        m_errorMessage.TrimRight( );

        if( elements.GetLength( ) )
            m_errorMessage += _TCHAR( ' ' ) + elements;

        Trigger ( m_errorMessage );

        // Free the buffer.
        LocalFree( msgBuff );
    }

    void CDiskObject::SetInternalErrorMessage( )
    /* ============================================================
        Function :        CDiskObject::SetInternalErrorMessage
        Description :    Sets the error message to the internal error
                        message
        Access :        Private

        Return :        void
        Parameters :    none

        Usage :            Call to set the error message.

       ============================================================*/
    {
        m_errorMessage = _T( "CDiskObject internal error" );
        Trigger ( m_errorMessage );
    }

    ////////////////////////////////////////
    // Helpers

    void CDiskObject::QualifyPath( CString& str )
    /* ============================================================
        Function :        CDiskObject::QualifyPath
        Description :    Creates a fully qualified path from "str".
        Access :        Private
        Return :        void
        Parameters :    CString& str    -    the path to qualify

        Usage :            Call to create a fully qualified path.

       ============================================================*/
    {

        str.Replace( _TCHAR( '/' ), _TCHAR( '\\' ) );

        // Append a trailing backslash to directory name
        if( str.GetLength( ) )
            if( str[ str.GetLength( ) - 1 ] != _TCHAR( '\\' ) )
                str += _TCHAR( '\\' );

        if( str.GetLength( ) < 2 || str.Left( 2) != "\\\\" )
            QualifyFile( str );

    }

    void CDiskObject::QualifyFile( CString& str )
    /* ============================================================
        Function :        CDiskObject::QualifyFile
        Description :    Creates a fully qualified path from "str".
        Access :        Private

        Return :        void
        Parameters :    CString& str    -    the filename to qualify

        Usage :            Call to create a fully qualified filename.

       ============================================================*/
    {
        str.Replace( _TCHAR( '/' ), _TCHAR( '\\' ) );

        _TCHAR drive[ _MAX_DRIVE ];
        _TCHAR dir[ _MAX_DIR ];
        _TCHAR fname[ _MAX_FNAME ];
        _TCHAR ext[ _MAX_EXT ];

        _tsplitpath( str, drive, dir, fname, ext );

        if( !_tcsclen( drive ) )
        {
            CString test( dir );
            // The name is not fully qualified.
            // We assume it to be relative the
            // current directory

            TCHAR currentDirectory[ _MAX_PATH ];
            ::GetCurrentDirectory( _MAX_PATH, currentDirectory );
            if( test.GetLength( ) > 2 && test.Left( 3 ) == _T( "..\\" ) )
            {

                TCHAR upDirectory[ _MAX_PATH ];
                while( test.GetLength( ) > 2 && test.Left( 3 ) == _T( "..\\" ) )
                {
                    ::SetCurrentDirectory( _T( ".." ) );
                    test = test.Right( test.GetLength( ) - 3 );
                }

                ::GetCurrentDirectory( _MAX_PATH, upDirectory );

                str = upDirectory;
                str += _TCHAR( '\\' );
                str += fname;
                str += ext;
                ::SetCurrentDirectory( currentDirectory );
            }
            else if ( test.GetLength( ) && test[ 0 ] == _TCHAR( '\\' ) )
            {
                // Start from root
                _tsplitpath( currentDirectory, drive, dir, fname, ext );
                str = drive + str;
            }
            else
            {
                str = _TCHAR( '\\' ) + str;
                str = currentDirectory + str;
            }
        }
    }

    CString CDiskObject::GetFileName( const CString& str )
    /* ============================================================
        Function :        CDiskObject::GetFileName
        Description :    Returns the file name part of "str".
        Access :        Private
        Return :        CString    -   
        Parameters :    CString str    -    The complete name to get

        Usage :            Call to get the filename from a fully
                        qualified path.

       ============================================================*/
    {
        CString instr( str );
        QualifyFile( instr );
        CString file;
        int found = instr.ReverseFind( _TCHAR( '\\' ) );
        if( found != -1 )
            file = instr.Right( str.GetLength( ) - ( found + 1 ) );

        return file;
    }

    CString CDiskObject::GetDirectoryName( const CString& str )
    /* ============================================================
        Function :        CDiskObject::GetDirectoryName
        Description :    Returns the directory name part of "str"
        Access :        Private
        Return :        CString    -   
        Parameters :    CString str    -    The complete name to check   

        Usage :            Call to get the directory from a fully
                        qualified path.

       ============================================================*/
    {
        CString instr( str );
        QualifyFile( instr );
        CString directory;
        int found = instr.ReverseFind( _TCHAR( '\\' ) );
        if( found != -1 )
            directory = instr.Left( found );

        return directory;
    }

    #pragma warning( default : 4706 )

  • 相关阅读:
    Redis实战(十)Redis常见问题及解决方案
    小团队构建大网站:中小研发团队架构实践
    Asp.net core 3.0
    图解TCP/IP
    TCP/IP协议
    Grid画边框
    WPF常用方法,事件驱动和控件遍历
    WPF中的画图
    WPF中的常用类汇总:
    WPF中的VisualTreeHelper
  • 原文地址:https://www.cnblogs.com/chuncn/p/1411093.html
Copyright © 2020-2023  润新知