⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfile.cpp

📁 跨平台C++基础库
💻 CPP
字号:

#include "MCRT/mfile.h"

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>

#define INITIALIZED_CHECK() \
    if ( this->m_fp == NULL ) \
    {\
        return 0; \
    }

MFile::MFile()
:m_fp(NULL)
{
}

MFile::~MFile()
{
    this->Close();
}

mInt32 MFile::Open( const char* pPath, mUInt32 openMode )
{
    mInt32 retVal  =   E_SUCCESS;

    //release resouces if has opened
    if ( this->m_fp != NULL )
    {
        this->Close();
    }

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        std::string strMode;
        if ( openMode & MFile::MO_RDONLY )
        {
            //check if file exist
            retVal  =   MFile::Exist( pPath );
            if ( retVal != E_SUCCESS )
            {
                break;
            }

            strMode.append( "r" );
        }
        else if ( openMode & MFile::MO_WRONLY )
        {
            strMode.append( "w" );
        }
        else if ( openMode & MFile::MO_RDWR )
        {
            //check if file exist
            retVal  =   MFile::Exist( pPath );
            if ( retVal != E_SUCCESS )
            {
                break;
            }

            strMode.append( "r" );
        }
        else if ( openMode & MFile::MO_APPEND )
        {
            strMode.append( "a" );
        }

        if ( openMode & MFile::MO_BINARY )
        {
            strMode.append( "b" );
        }
        else if ( openMode & MFile::MO_TEXT )
        {
            strMode.append( "t" );
        }

        if ( (openMode & MFile::MO_RDWR) || (openMode & MFile::MO_APPEND) )
        {
            strMode.append( "+" );
        }

        this->m_fp  =   ::fopen( pPath, strMode.c_str() );
        if ( this->m_fp == NULL )
        {
            retVal  =   E_FILE_OPEN;
            break;
        }

        this->m_strPath =   pPath;
        this->m_mode    =   openMode;
    }

    return retVal;
}

mInt32 MFile::Close()
{
    if ( this->m_fp != NULL )
    {
        ::fclose( this->m_fp );
        this->m_fp  =   NULL;
    }

    return E_SUCCESS;
}

bool MFile::IsOpen() const
{
    return ( this->m_fp != NULL );
}

mLong MFile::GetLength()
{
    INITIALIZED_CHECK();

    //save locale
    mLong   pos =   ::ftell( this->m_fp );

    mLong   posBegin    =   this->SeekToBegin();
    mLong   posEnd      =   this->SeekToEnd();

    //restore locale
    ::fseek( this->m_fp, pos, SEEK_SET );

    return posEnd - posBegin;
}

mLong MFile::Seek( mLong offset, MFile::POS_TYPE origin )
{
    INITIALIZED_CHECK();

    //check if exceeds file length
    if( offset+origin > this->GetLength() )
    {
        return 0;
    }

    ::fseek( this->m_fp, offset, origin );
    return this->Tell();
}

mLong MFile::SeekToBegin()
{
    INITIALIZED_CHECK();

    ::rewind( this->m_fp );
    return this->Tell();
}

mLong MFile::SeekToEnd()
{
    INITIALIZED_CHECK();

    ::fseek( this->m_fp, 0, SEEK_END );
    return this->Tell();
}

mLong MFile::Tell()
{
    INITIALIZED_CHECK();

    return ::ftell(this->m_fp);
}

mLong MFile::Read( void* pBuf, mLong bufLen )
{
    INITIALIZED_CHECK();

    mLong   bytesRead   =   0;
    mLong   bytesUnit   =   M_BLOCK_BUF_SIZE;

    if ( bufLen > M_BLOCK_BUF_SIZE )
    {
        mLong   countBlock      =   bufLen / M_BLOCK_BUF_SIZE;
        mLong   lastBlockSize   =   bufLen % M_BLOCK_BUF_SIZE;

        for ( mLong i = 0; i < countBlock; ++ i )
        {
            bytesUnit   =   ::fread( (unsigned char*)pBuf + i*M_BLOCK_BUF_SIZE, sizeof(unsigned char), M_BLOCK_BUF_SIZE, this->m_fp );
            bytesRead   +=  bytesUnit;
            if ( bytesUnit != M_BLOCK_BUF_SIZE )
            {
                break;
            }
        }
        if ( (bytesUnit == M_BLOCK_BUF_SIZE) && (lastBlockSize != 0) )
        {
            bytesRead   +=  ::fread( (unsigned char*)pBuf + countBlock*M_BLOCK_BUF_SIZE, sizeof(unsigned char), lastBlockSize, this->m_fp );
        }
    }
    else
    {
        bytesRead   =   ::fread( pBuf, sizeof(unsigned char), bufLen, this->m_fp );
    }

    return bytesRead;
}

mLong MFile::Write( const void* pBuf, mLong dataLen )
{
    INITIALIZED_CHECK();

    mLong   bytesWrite  =   0;
    mLong   bytesUnit   =   M_BLOCK_BUF_SIZE;

    if ( dataLen > M_BLOCK_BUF_SIZE )
    {
        mLong   countBlock      =   dataLen / M_BLOCK_BUF_SIZE;
        mLong   lastBlockSize   =   dataLen % M_BLOCK_BUF_SIZE;

        for ( mLong i = 0; i < countBlock; ++ i )
        {
            bytesUnit   =   ::fwrite( (unsigned char*)pBuf + i*M_BLOCK_BUF_SIZE, sizeof(unsigned char), M_BLOCK_BUF_SIZE, this->m_fp );
            bytesWrite  +=  bytesUnit;
            if ( bytesUnit != M_BLOCK_BUF_SIZE )
            {
                break;
            }
        }
        if ( (bytesUnit == M_BLOCK_BUF_SIZE) && (lastBlockSize != 0) )
        {
            bytesWrite  +=  ::fwrite( (unsigned char*)pBuf + countBlock*M_BLOCK_BUF_SIZE, sizeof(unsigned char), lastBlockSize, this->m_fp );
        }
    }
    else
    {
        bytesWrite  =   ::fwrite( pBuf, sizeof(unsigned char), dataLen, this->m_fp );
    }

    return bytesWrite;
}

bool MFile::Flush()
{
    if ( this->m_fp != NULL )
    {
        // fflush no use, so close and reopen
        ::fclose( this->m_fp );
        this->m_fp  =   NULL;
        this->Open( this->m_strPath.c_str(), this->m_mode );
    }

    return true;
}

mLong MFile::Resize( mLong len )
{
    if ( this->m_fp == NULL )
    {
        return E_FILE_OPEN;
    }

    char*   pBuf    =   new char[M_BLOCK_BUF_SIZE];
    if ( pBuf == NULL )
    {
        return E_MEMORY_INSUFFICIENT;
    }
    ::memset( pBuf, 0, M_BLOCK_BUF_SIZE );

    mLong   dataLen =   len - this->GetLength();
    this->SeekToEnd();

    // append blank data to file
    mLong   bytesWrite  =   0;
    mLong   bytesUnit   =   M_BLOCK_BUF_SIZE;
    if ( dataLen > M_BLOCK_BUF_SIZE )
    {
        mLong   countBlock      =   dataLen / M_BLOCK_BUF_SIZE;
        mLong   lastBlockSize   =   dataLen % M_BLOCK_BUF_SIZE;

        for ( mLong i = 0; i < countBlock; ++ i )
        {
            bytesUnit   =   ::fwrite( (unsigned char*)pBuf + i*M_BLOCK_BUF_SIZE, sizeof(unsigned char), M_BLOCK_BUF_SIZE, this->m_fp );
            bytesWrite  +=  bytesUnit;
            if ( bytesUnit != M_BLOCK_BUF_SIZE )
            {
                break;
            }
        }
        if ( (bytesUnit == M_BLOCK_BUF_SIZE) && (lastBlockSize != 0) )
        {
            bytesWrite  +=  ::fwrite( (unsigned char*)pBuf + countBlock*M_BLOCK_BUF_SIZE, sizeof(unsigned char), lastBlockSize, this->m_fp );
        }
    }
    else
    {
        bytesWrite  =   ::fwrite( pBuf, sizeof(unsigned char), dataLen, this->m_fp );
    }

    if ( bytesWrite != dataLen )
    {
        return E_FILE_WRITE;
    }

    return E_SUCCESS;
}

mInt32 MFile::Exist( const char* pPath )
{
    mInt32  retVal  =   E_SUCCESS;

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        //check if NULL pointer
        if ( pPath == NULL )
        {
            retVal  =   E_PARAM_POINTER_NULL;
            break;
        }

        //check if path len exceed system's max path len
        if ( ::strlen( pPath ) > PATH_MAX )
        {
            retVal  =   E_FILE_PATH_LEN;
            break;
        }

        struct stat fileStat;
        //check if file exist
        if ( ::stat( pPath, &fileStat ) != 0 )
        {
            retVal  =   E_FILE_NOT_EXIST;
            break;
        }
    }

    return retVal;
}

mInt32 MFile::Clear( const char* pFile )
{
    mInt32  retVal  =   E_SUCCESS;

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        //check if file exist
        retVal  =   MFile::Exist( pFile );
        if ( retVal != E_SUCCESS )
        {
            break;
        }

        MFile   mfile;
        mfile.Open( pFile, MFile::MO_WRONLY );
        mfile.Close();
    }

    return retVal;
}

mInt32 MFile::Create( const char* pFile, mLong initLen )
{
    mInt32  retVal  =   E_SUCCESS;

    MFile   mfile;

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        //check param
        if ( pFile == NULL )
        {
            retVal  =   E_PARAM_POINTER_NULL;
            break;
        }

        //open and clear file
        retVal  =   mfile.Open( pFile, MFile::MO_WRONLY );
        if ( retVal != E_SUCCESS )
        {
            break;
        }

        //if initialized length is 0, then is OK
        if ( initLen == 0 )
        {
            break;
        }

        //add NULL data to file
        char*   pBuf    =   new char[initLen];
        if ( pBuf == NULL )
        {
            retVal  =   E_MEMORY_INSUFFICIENT;
            break;
        }
        ::memset( pBuf, 0, initLen );
        if ( mfile.Write( pBuf, initLen ) != initLen )
        {
            retVal  =   E_FILE_WRITE;
            break;
        }

        delete [] pBuf;
    }

    if ( mfile.IsOpen() )
    {
        mfile.Close();
    }
    return retVal;
}

mInt32 MFile::Compare( const char* pDestFile, const char* pSrcFile )
{
    mInt32  retVal  =   E_SUCCESS;

    MFile   mfileSrc;
    MFile   mfileDest;
    char*   pBufSrc =   NULL;
    char*   pBufDest=   NULL;

    struct stat srcFileStat;
    struct stat destFileStat;
    mLong       bytesUnit   =   0;

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        //check file whether exists
        retVal  |=  MFile::Exist( pDestFile );
        retVal  |=  MFile::Exist( pSrcFile );
        if ( retVal != E_SUCCESS )
        {
            break;
        }

        //check file size first, previous exist assure ::stat success
        ::stat( pSrcFile, &srcFileStat );
        ::stat( pDestFile, &destFileStat );
        if ( srcFileStat.st_size != destFileStat.st_size )
        {
            retVal  =   E_GENERAL;
            break;
        }

        //open file
        retVal  =   mfileSrc.Open( pSrcFile, MFile::MO_RDONLY );
        retVal  =   mfileDest.Open( pDestFile, MFile::MO_RDONLY );
        if ( retVal != E_SUCCESS )
        {
            break;
        }

        //allocate compare resources
        pBufSrc =   new char[M_BLOCK_BUF_SIZE];
        pBufDest=   new char[M_BLOCK_BUF_SIZE];
        if ( (pBufSrc == NULL) || (pBufDest == NULL) )
        {
            retVal  =   E_MEMORY_INSUFFICIENT;
            break;
        }

        //check if the contents are same
        bytesUnit   =   0;
        while ( (bytesUnit = mfileSrc.Read( pBufSrc, M_BLOCK_BUF_SIZE )) > 0 )
        {
            mfileDest.Read( pBufDest, M_BLOCK_BUF_SIZE );
            if ( ::memcmp( pBufDest, pBufSrc, bytesUnit ) != 0 )
            {
                retVal  =   E_GENERAL;
                break;
            }
        }
    }

    mfileSrc.Close();
    mfileDest.Close();
    delete [] pBufSrc;
    delete [] pBufDest;
    return retVal;
}

mInt32 MFile::Copy( const char* pDestFile, const char* pSrcFile )
{
    mInt32  retVal  =   E_SUCCESS;

    MFile   fileDest, fileSrc;
    char*   pBuf    =   NULL;

    mInt32  dataRead    =   0;

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        if ( (pDestFile == NULL) || (pSrcFile == NULL) )
        {
            retVal  =   E_PARAM_POINTER_NULL;
            break;
        }

        retVal  =   fileDest.Open( pDestFile, MFile::MO_WRONLY | MFile::MO_BINARY );
        if ( retVal != E_SUCCESS )
        {
            break;
        }

        retVal  =   fileSrc.Open( pSrcFile, MFile::MO_RDONLY | MFile::MO_BINARY );
        if ( retVal != E_SUCCESS )
        {
            break;
        }

        pBuf    =   new char[M_BLOCK_BUF_SIZE];
        if ( pBuf == NULL )
        {
            retVal  =   E_MEMORY_INSUFFICIENT;
            break;
        }

        dataRead    =   fileSrc.Read( pBuf, M_BLOCK_BUF_SIZE );
        while ( dataRead > 0 )
        {
            if ( fileDest.Write( pBuf, dataRead ) != dataRead )
            {
                retVal  =   E_FILE_WRITE;
                break;
            }

            dataRead    =   fileSrc.Read( pBuf, M_BLOCK_BUF_SIZE );
        }
    }

    fileDest.Close();
    fileSrc.Close();
    delete [] pBuf;
    return retVal;
}

mLong MFile::Read( const char* pFile, mLong offset, void* pBuf, mLong bufLen )
{
    mLong   dataRead    =   0;

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        MFile   mfile;
        if ( mfile.Open( pFile, MFile::MO_RDONLY | MFile::MO_BINARY ) != E_SUCCESS )
        {
            break;
        }

        if ( mfile.Seek( offset, MFile::MPOS_BEGIN ) != offset )
        {
            break;
        }

        dataRead    =   mfile.Read( pBuf, bufLen );
    }

    return dataRead;
}

mLong MFile::Write( const char* pFile, mLong offset, void* pBuf, mLong dataLen )
{
    mLong   dataWrite   =   0;

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        MFile   mfile;
        if ( mfile.Open( pFile, MFile::MO_RDWR | MFile::MO_BINARY ) != E_SUCCESS )
        {
            break;
        }

        if ( mfile.Seek( offset, MFile::MPOS_BEGIN ) != offset )
        {
            break;
        }

        dataWrite   =   mfile.Write( pBuf, dataLen );
    }

    return dataWrite;
}

mLong MFile::Append( const char* pFile, const void* pBuf, mLong dataLen )
{
    mLong   dataWrite   =   0;

    for ( int iOnce = 0; iOnce < 1; ++ iOnce ) // convenient for releasing resources while failed
    {
        MFile   mfile;
        if ( mfile.Open( pFile, MFile::MO_APPEND | MFile::MO_BINARY ) != E_SUCCESS )
        {
            break;
        }

        dataLen =   mfile.Write( pBuf, dataLen );
    }

    return dataWrite;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -