基于魔兽哈希算法的Ogre资源文件扩展的设计与实现

一、功能需求

1、需要实现的功能:

(1)、创建、打开和关闭资源包。

(2)、压缩资源包。消除数据添加、修改和删除带来的数据碎片,扩展索引表容量,重设资源包密钥。

(3)、合并资源包。将外部的资源包整合进当前打开的资源包。

(4)、释放资源文件。将资源包内的任意文件释放到磁盘。

(5)、创建文件夹。

(6)、(批量)添加文件。可以指定文件的独立密钥与压缩选项。

(7)、从文件夹添加数据(包括文件夹与文件)。可以指定文件的独立密钥与压缩选项。

(8)、(批量)更新文件。可以选择按列表顺序与按文件名两种方式进行数据更新。

(9)、(批量)复制、剪切、粘贴、删除和重命名单元。

(10)、查看和修改资源属性。

(11)、文件生成格式为.pkg格式

(12)、资源管理程序新增需求

ogre资源管理适配器,ogre本身有抽象的文件夹和文件流接口:zip文件和第三方自定义文件。实现这些接口可以让ogre使用第三方资源管理器,即我们现在做的这套。

2、性能需求:

    压缩算法选择:压缩率高。加密算法选择:机密性好。同时在时间上有一定Deadline.

3、界面要求:

     直观,大方,美观。

本软件在UI设计方面采用的是wxWidgets库,由于本库在跨平台方面做的已经比较成熟,可以满足软件移植的需要,而且它对常用的控件进行了封装,因而在设计的过程中可以减少界面设计的开销,可以把精力放在重点算法的实现上。本部分给出整个窗体的界面元素及其相关说明。

●  采用的wxWidgets图形用户界面(GUl)标准,感官上稍异于传统windows界面显示效果;

●  屏幕布局采用wxWidgets中的布局控件进行,尽量满足多分辨率的显示问题;

●  使用在图形用户界面上的软件组件,包括:

Ø  菜单:wxMenu

Ø  工具栏:wxToolBar

Ø  标准按钮:wxButton

Ø  树形控件:wxTreeCtrl

Ø  文件列表控件:wxListCtrl

Ø  文本显示框:wxTextCtrl

Ø  状态栏:wxStatusBar

●  快捷键:(参照菜单项)

●  各种显示格式的规定,包括:

Ø  不同情况下文字的对齐方式;

Ø  不同情况下数字的表现格式与对齐方式

Ø  程序和文件的编码方式采用Unicode编码

 

●  错误信息显示标准;

 

1、菜单

    文件(E)-------新建(N)   Ctrl + N

                     |----打开(O)   Ctrl + O

                     |----重新打开(R)

                     |----关闭(O)

                     |----历史记录----…

                     |——————————

                     |----信息(I)

                     |——————————

                     |----退出(Q)   Alt + Q

    查看(V)-------ü工具栏(T)

                     |----ü预览(P)

                     |——————————

                     |----®大图标(G)

                     |----®小图标(M)

                     |----®列表(L)

                     |----®详细资料(D)

    操作(E)-------打开(O)

                     |----打开方式…(W)

                     |——————————

                     |----解压缩(E)              Ctrl + E

                     |----重命名(R)              F2

                     |----删除(D)          Delete

                     |——————————

                     |----属性(P)

                     |——————————

                     |----新建文件夹(N)

                     |----添加文件(A)

                     |----添加文件夹(T)

                     |——————————

                     |----选择列表文件(L)

                     |----全部解压(X)

                     |----重新压缩(C)

    选项(P)-------文件类型选项(O)   F6

                     |----语言------------®English

                                          |----®Chinese

                                          |----®Russian

    帮助(H)-------关于(A)

2、工具栏

BTN_新建

BTN_打开

——————

BTN_信息

——————

BTN_

——————

BTN_加压缩

BTN_删除

——————

BTN_添加文件

BTN_添加文件夹

——————

BTN_大图标

BTN_小图标

BTN_列表

BTN_详细资料

——————

LIST_查找

3、主界面

左:wxTreeCtrl

右:wxListCtrl

下:wxTextCtrl

底:wxStatusBar

4、列表框右键菜单

|----打开(O)

                     |----打开方式…(W)

                     |——————————

                     |----解压缩(E)      

                     |----重命名(R)      

                     |----删除(D)

                     |——————————

                     |----属性(P)

                     |——————————

                     |----新建文件夹(N)

                     |----添加文件(A)

                     |----添加文件夹(T)


 

4、可以扩展的功能:

加密算法的可选择性、PKG文件的压缩

 

5、本系统目前还没有完成的功能如下:

(1).  加密算法及其加密算法的可选择性

       (2). PKG文件的压缩

 

二、程序系统结构设计

    1.整体逻辑框图

    2.PKG包文件格式结
    2.PKG包文件格式结构设计


3.空闲块链内存表示


4.目录树逻辑结构图


三、算法设计

1、文件添加流程


    2、文件删除操作流程


    3、PKG文件的创建及其PKG文件的读取流程


    4、文件修改流程【暂时没有加入】


    5、文件释放流程


6、 文件/文件夹重命名流程


四、接口设计

1、 PKG包操作

CreatePKG[创建PKG文件]

函数声明:
 
bool CreatePKG( char* sFilePath, long nTableSize );
 
函数说明:
 
新建一个空的PKG文件。
 
返回值:
 
bool,true表示成功,false表示失败。
 
参数列表:
 
sFilePath
 [String],保存PKG文件的路径。
 
nTableSize
 [DWord],新建PKG文件的索引表大小。
 


 

OpenPKG[打开PKG文件]

函数声明:
 
bool OpenPKG( char* sFilePath );
 
函数说明:
 
打开一个存在的PKG文件。
 
返回值:
 
bool,true表示成功,false表示失败。
 
参数列表:
 
sFilePath
 [String],PKG文件的路径。
 


 

ClosePKG[关闭PKG文件]

函数声明:
 
bool ClosePKG();
 
函数说明:
 
关闭PKG文件,并做出相应的收尾工作。
 
返回值:
 
bool,true表示成功,false表示失败。
 


 

GetFileNum[取得PKG包中文件个数]

函数声明:
 
long GetFileNum();
 
函数说明:
 
[long],取得当前打开PKG文件中的文件个数。
 
返回值:
 
long:PKG文件中的文件个数。
 


 

GetTableSize [取得索引表的大小]

函数声明:
 
long GetTableSize();
 
函数说明:
 
取得指定文件的大小。
 
返回值:
 
[long],取得PKG头部索引表大小。
 
返回值:
 
long:PKG文件中的索引表的大小。
 


 

GetTableOffset[取得索引表偏移]

函数声明:
 
long GetTableOffset();
 
函数说明:
 
取得PKG文件中索引表的偏移量。
 
返回值:
 
long,索引表偏移量。
 


GetPKGVersion[获取PKG文件版本号]

函数声明:
 
long GetPKGVersion();
 
函数说明:
 
取得PKG文件的版本号。
 
返回值:
 
[long],取得PKG文件版本号。
 


 

2、 PKG内部文件操作

AddFileR[向PKG文件中添加文件]

函数声明:
 
bool ddFileR( char* strFileName, char* strRelName );
 
函数说明:
 
将一个文件添加到已经打开的PKG中。
 
返回值:
 
bool,成功:True;失败:false.
 
参数列表:
 
strFileName
 [String],需要加入文件的路径。
 
strRelName
 [String],加入到PKG文件中的相对路径。
 


 

DelFile[删除PKG文件中指定的文件]

函数声明:
 
bool  DelFile(char *sFileName );
 
函数说明:
 
按照指定的文件名将此文件删除。
 
返回值:
 
bool,true表示成功,false表示失败。
 
参数列表:
 
sFileName
 [String],文件名
 


 

DelFolder [删除PKG文件中指定的文件夹]

函数声明:
 
bool  DelFolder( char *dirPath );
 
函数说明:
 
删除PKG文件中相对路径中的目录。
 
返回值:
 
bool,true表示成功,false表示失败。
 
参数列表:
 
dirPath
 [String],PKG相对路径名
 


 

AddFolderR [添加文件夹]

函数声明:
 
Void AddFolderR(char * szFolderPath, char* strRelName );
 
函数说明:
 
向PKG相对路径中,递归添加目录。
 
返回值:
 
 
 
参数列表:
 
szFolderPath
 [String]要添加的目录路径。
 
strRelName
 [String]添加到的路径。
 


 

GetFileLen[取得文件大小]

函数声明:
 
long GetFileLen( string sFileName );
 
函数说明:
 
取得指定文件的大小。
 
返回值:
 
[long],取得指定文件名的文件大小。
 
参数列表:
 
sFileName
 [String],指定的文件名。
 


 

GetFileOffset[取得文件偏移量]

函数声明:
 
long GetFileOffset( String sFileName );
 
函数说明:
 
取得已打开的PKG内指定序号文件的地址偏移,可使用此地址偏移直接取得数据。
 
返回值:
 
long,偏移地址
 
参数列表:
 
sFileName
 [String],指定的文件名。
 


 

ReleaseFile[释放文件]

函数声明:
 
bool ReleaseFile( char* sSrcFileName, char* sDesDir );

bool ReleaseFile( unsigned long dwIndex, char* sDesDir );
 
函数说明:
 
将包中指定文件释放到硬盘。
 
返回值:
 
bool,true表示成功,false表示失败。
 
参数列表:
 
sSrcFileName
 [String],PKG中指定的文件名。
 
sDesDir
 [String],释放到的磁盘路径,没有则创建。
 
dwIndex
 [DWORD],释放文件的索引。
 


 

RenameFile [重命名PKG中的文件]

函数声明:
 
bool RenameFile( char* strOldName, char* strNewName );;
 
函数说明:
 
将包中指定文件进行重命名。
 
返回值:
 
bool,true表示成功,false表示失败。
 
参数列表:
 
strOldName
 [String],PKG中源文件名。
 
strNewName
 [String],新文件名。
 


 

3、 PKG其它操作

五、Ogre资源扩展

    1、修改OgreRoot和OgreStableHeaders,在其中仿照zip文件加入响应代码。

    2、加入OgrePkg文件(进行扩充资源类型)

view plaincopy to clipboardprint?
#ifndef __Pkg_H__  
#define __Pkg_H__  
 
#include "OgrePrerequisites.h"  
 
#include "OgreArchive.h"  
#include "OgreArchiveFactory.h"      
 
typedef struct pkg_dirent   PKG_DIRENT;  
typedef struct pkg_dirent   PKG_STAT;  
//--------------------------------------------------------------------------  
// 提前声明,防止文件的依赖  
typedef class CPkg          PKG;  
typedef class CPkgDir       PKG_DIR;  
typedef class CPkgFile      PKG_FILE;  
 
namespace Ogre {  
 
 
    class _OgreExport PkgArchive : public Archive   
    {  
    protected:  
 
        PKG* mPkg;  
        PKG_DIR* mPkgDir;  
        // pkg中文件列表  
        FileInfoList mFileList;  
    public:  
        PkgArchive(const String& name, const String& archType );  
        ~PkgArchive();  
 
        // 不区分大小写  
        bool isCaseSensitive(void) const { return false; }  
 
        void load();  
        void unload();  
 
        DataStreamPtr open(const String& filename) const;  
        StringVectorPtr list(bool recursive = true, bool dirs = false);  
        FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false);  
        StringVectorPtr find(const String& pattern, bool recursive = true,  
            bool dirs = false);  
        FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,  
            bool dirs = false);  
        bool exists(const String& filename);  
        time_t getModifiedTime(const String& filename);  
 
    };  
 
    //--------------------------------------------------------------------------  
    // 用于Pkg文件的ArchiveFactory  
    class _OgrePrivate PkgArchiveFactory : public ArchiveFactory  
    {  
    public:  
        virtual ~PkgArchiveFactory() {}  
        const String& getType(void) const;  
        Archive *createInstance( const String& name )   
        {  
            return OGRE_NEW PkgArchive(name, "Pkg");  
        }  
        void destroyInstance( Archive* arch) { OGRE_DELETE arch; }  
    };  
 
    //--------------------------------------------------------------------------  
    // 处理PKG包中文件  
    class _OgrePrivate PkgDataStream : public DataStream  
    {  
    protected:  
        PKG_FILE* mPkgFile;  
    public:  
        PkgDataStream(PKG_FILE* pkgFile, size_t uncompressedSize);  
        PkgDataStream(const String& name, PKG_FILE* pkgFile, size_t uncompressedSize);  
        ~PkgDataStream();  
 
        size_t read(void* buf, size_t count);  
        void skip(long count);  
        void seek( size_t pos );  
        size_t tell(void) const;  
        bool eof(void) const;  
        void close(void);  
 
    };  
 
}  
 
#endif 
#ifndef __Pkg_H__
#define __Pkg_H__

#include "OgrePrerequisites.h"

#include "OgreArchive.h"
#include "OgreArchiveFactory.h"   

typedef struct pkg_dirent   PKG_DIRENT;
typedef struct pkg_dirent   PKG_STAT;
//--------------------------------------------------------------------------
// 提前声明,防止文件的依赖
typedef class CPkg          PKG;
typedef class CPkgDir  PKG_DIR;
typedef class CPkgFile     PKG_FILE;

namespace Ogre {


    class _OgreExport PkgArchive : public Archive
    {
    protected:

        PKG* mPkg;
        PKG_DIR* mPkgDir;
        // pkg中文件列表
        FileInfoList mFileList;
    public:
        PkgArchive(const String& name, const String& archType );
        ~PkgArchive();

        // 不区分大小写
        bool isCaseSensitive(void) const { return false; }

        void load();
        void unload();

        DataStreamPtr open(const String& filename) const;
        StringVectorPtr list(bool recursive = true, bool dirs = false);
        FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false);
        StringVectorPtr find(const String& pattern, bool recursive = true,
            bool dirs = false);
        FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
            bool dirs = false);
        bool exists(const String& filename);
        time_t getModifiedTime(const String& filename);

    };

    //--------------------------------------------------------------------------
    // 用于Pkg文件的ArchiveFactory
    class _OgrePrivate PkgArchiveFactory : public ArchiveFactory
    {
    public:
        virtual ~PkgArchiveFactory() {}
        const String& getType(void) const;
        Archive *createInstance( const String& name )
        {
            return OGRE_NEW PkgArchive(name, "Pkg");
        }
        void destroyInstance( Archive* arch) { OGRE_DELETE arch; }
    };

    //--------------------------------------------------------------------------
    // 处理PKG包中文件
    class _OgrePrivate PkgDataStream : public DataStream
    {
    protected:
        PKG_FILE* mPkgFile;
    public:
        PkgDataStream(PKG_FILE* pkgFile, size_t uncompressedSize);
        PkgDataStream(const String& name, PKG_FILE* pkgFile, size_t uncompressedSize);
        ~PkgDataStream();

        size_t read(void* buf, size_t count);
        void skip(long count);
        void seek( size_t pos );
        size_t tell(void) const;
        bool eof(void) const;
        void close(void);

    };

}

#endif
 

view plaincopy to clipboardprint?
#include "OgreStableHeaders.h"  
 
#include "OgrePkg.h"  
 
#include "OgreLogManager.h"  
#include "OgreException.h"  
#include "OgreStringVector.h"  
#include "OgreRoot.h"  
 
#include "./pkg/TsPkg.h"  // 接口  
 
namespace Ogre {  
 
    //-----------------------------------------------------------------------  
    PkgArchive::PkgArchive(const String& name, const String& archType )  
        : Archive(name, archType), mPkgDir(0)  
    {  
        mPkg = new CPkg();  
    }  
    //-----------------------------------------------------------------------  
    PkgArchive::~PkgArchive()  
    {  
        unload();  
    }  
    //-----------------------------------------------------------------------  
    void PkgArchive::load()  
    {  
        char pkgPath[MAX_PATH];  
        strcpy_s( pkgPath, MAX_PATH, mName.c_str() );  
 
        mPkgDir = mPkg->pkg_open( pkgPath );  
        if (mPkgDir)  
        {  
            mPkgDir->pkg_dir_open(mName);  
              
            mPkgDir->pkg_dir_read();              
 
 
            vector<PKG_DIRENT> *vec = mPkgDir->GetDir();  
            vector<PKG_DIRENT>::iterator pkgdir = (*vec).begin();  
            while ( pkgdir != vec->end() )  
            {  
                  
                FileInfo info;  
                info.archive = this;  
                // Get basename / path  
                StringUtil::splitFilename((*pkgdir).d_name, info.basename, info.path);  
                info.filename = (*pkgdir).d_name;  
                // Get sizes  
                info.compressedSize = static_cast<size_t>((*pkgdir).d_csize);  
                info.uncompressedSize = static_cast<size_t>((*pkgdir).st_size);  
                // folder entries  
                if (info.basename.empty())  
                {  
                    info.filename = info.filename.substr (0, info.filename.length () - 1);  
                    StringUtil::splitFilename(info.filename, info.basename, info.path);  
                    // Set compressed size to -1 for folders; anyway nobody will check  
                    // the compressed size of a folder, and if he does, its useless anyway  
                    info.compressedSize = size_t (-1);  
                }  
                mFileList.push_back(info);  
                  
                pkgdir++;  
            }  
 
        }  
    }  
    //-----------------------------------------------------------------------  
    void PkgArchive::unload()  
    {  
        if (mPkgDir)  
        {  
            mPkgDir->pkg_dir_close();  
            mPkgDir = 0;  
            mFileList.clear();  
        }  
 
    }  
    //-----------------------------------------------------------------------  
    DataStreamPtr PkgArchive::open(const String& filename) const 
    {  
        // Format not used here (always binary)  
        char openpath[MAX_PATH];  
        strcpy_s( openpath, MAX_PATH, filename.c_str() );  
 
        filesystem::path filepath( openpath,filesystem::native );  
        filepath.normalize();  
        string dirpath = filepath.branch_path().string();  
 
        PKG_FILE* pkgFile =  mPkgDir->pkg_dir_openRel(dirpath);  
 
        char strFilename[_MAX_FNAME];  
        strcpy_s( strFilename, _MAX_FNAME, filepath.leaf().c_str() );  
        pkgFile->pkg_file_open( strFilename );  
        if (pkgFile < 0)  
        {  
            // return null pointer  
            return DataStreamPtr();  
        }  
 
        // Get uncompressed size too  
        PKG_STAT zstat;  
        //mPkgDir->pkg_dir_stat(filename, &zstat);  
        pkgFile->pkg_file_stat( &zstat );  
 
        // Construct & return stream  
        return DataStreamPtr(OGRE_NEW PkgDataStream(filename, pkgFile, static_cast<size_t>(zstat.st_size)));  
    }  
    //-----------------------------------------------------------------------  
    StringVectorPtr PkgArchive::list(bool recursive, bool dirs)  
    {  
        StringVectorPtr ret = StringVectorPtr(OGRE_NEW_T(StringVector, MEMCATEGORY_GENERAL)(), SPFM_DELETE_T);  
 
        FileInfoList::iterator i, iend;  
        iend = mFileList.end();  
        for (i = mFileList.begin(); i != iend; ++i)  
            if ((dirs == (i->compressedSize == size_t (-1))) &&  
                (recursive || i->path.empty()))  
                ret->push_back(i->filename);  
 
        return ret;  
    }  
    //-----------------------------------------------------------------------  
    FileInfoListPtr PkgArchive::listFileInfo(bool recursive, bool dirs)  
    {  
        FileInfoList* fil = OGRE_NEW_T(FileInfoList, MEMCATEGORY_GENERAL)();  
        FileInfoList::const_iterator i, iend;  
        iend = mFileList.end();  
        for (i = mFileList.begin(); i != iend; ++i)  
            if ((dirs == (i->compressedSize == size_t (-1))) &&  
                (recursive || i->path.empty()))  
                fil->push_back(*i);  
 
        return FileInfoListPtr(fil, SPFM_DELETE_T);  
    }  
    //-----------------------------------------------------------------------  
    StringVectorPtr PkgArchive::find(const String& pattern, bool recursive, bool dirs)  
    {  
        recursive = true;  
        StringVectorPtr ret = StringVectorPtr(OGRE_NEW_T(StringVector, MEMCATEGORY_GENERAL)(), SPFM_DELETE_T);  
        // If pattern contains a directory name, do a full match  
        bool full_match = (pattern.find ('/') != String::npos) ||  
            (pattern.find ('//') != String::npos);  
 
        FileInfoList::iterator i, iend;  
        iend = mFileList.end();  
        for (i = mFileList.begin(); i != iend; ++i)  
            if ((dirs == (i->compressedSize == size_t (-1))) &&  
                (recursive || full_match || i->path.empty()))  
                // Check basename matches pattern (pkg is case insensitive)  
                if (StringUtil::match(full_match ? i->filename : i->basename, pattern, false))  
                    ret->push_back(i->filename);  
 
        return ret;  
    }  
    //-----------------------------------------------------------------------  
    FileInfoListPtr PkgArchive::findFileInfo(const String& pattern,   
        bool recursive, bool dirs)  
    {  
        recursive = true;  
        dirs = false;  
        FileInfoListPtr ret = FileInfoListPtr(OGRE_NEW_T(FileInfoList, MEMCATEGORY_GENERAL)(), SPFM_DELETE_T);  
        // If pattern contains a directory name, do a full match  
        bool full_match = (pattern.find ('/') != String::npos) ||  
            (pattern.find ('//') != String::npos);  
 
        FileInfoList::iterator i, iend;  
        iend = mFileList.end();  
        for (i = mFileList.begin(); i != iend; ++i)  
        {  
            if ((dirs == (i->compressedSize == size_t (-1))) &&  
                (recursive || full_match || i->path.empty()))  
            {  
                 //Check name matches pattern (pkg is case insensitive)  
                if (StringUtil::match(full_match ? i->filename : i->basename, pattern, false))  
                {  
                    ret->push_back(*i);  
                }  
            }  
        }  
 
        return ret;  
    }  
    //--------------------------------------------------------------------  
    //bool PkgArchive::exists(const String& filename)  
    //{  
    //    PKG_STAT pkgstat;  
    //    return mPkgDir->pkg_dir_stat( filename, &pkgstat );  
    //}  
    //---------------------------------------------------------------------  
    //-----------------------------------------------------------------------  
    bool PkgArchive::exists(const String& filename)  
    {  
        PKG_STAT pkgstat;  
        return mPkgDir->pkg_dir_stat( filename, &pkgstat );  
    }  
    //---------------------------------------------------------------------   
    time_t PkgArchive::getModifiedTime(const String& filename)  
    {  
        // Pkglib doesn't yet support getting the modification time of individual files  
        // so just check the mod time of the pkg itself  
        struct stat tagStat;  
        bool ret = (stat(mName.c_str(), &tagStat) == 0);  
 
        if (ret)  
        {  
            return tagStat.st_mtime;  
        }  
        else 
        {  
            return 0;  
        }  
 
    }  
    //-----------------------------------------------------------------------  
    //-----------------------------------------------------------------------  
    //-----------------------------------------------------------------------  
    PkgDataStream::PkgDataStream(PKG_FILE* pkgFile, size_t uncompressedSize)  
        : mPkgFile(pkgFile)  
    {  
        mSize = uncompressedSize;  
    }  
    //-----------------------------------------------------------------------  
    PkgDataStream::PkgDataStream(const String& name, PKG_FILE* pkgFile, size_t uncompressedSize)  
        :DataStream(name), mPkgFile(pkgFile)  
    {  
        mSize = uncompressedSize;  
    }  
    //-----------------------------------------------------------------------  
    PkgDataStream::~PkgDataStream()  
    {  
        close();  
    }  
    //-----------------------------------------------------------------------  
    size_t PkgDataStream::read(void* buf, size_t count)  
    {  
        int r = mPkgFile->pkg_file_read((char*)buf, (int)count);  
        if (r<0)   
        {// 文件读取失败处理  
            return 0;  
        }  
        return (size_t) r;  
    }  
    //-----------------------------------------------------------------------  
    void PkgDataStream::skip(long count)  
    {  
        mPkgFile->pkg_seek(static_cast<long>(count));  
    }  
    //-----------------------------------------------------------------------  
    void PkgDataStream::seek( size_t pos )  
    {  
        mPkgFile->pkg_seek( static_cast<long>(pos));  
    }  
    //-----------------------------------------------------------------------  
    size_t PkgDataStream::tell(void) const 
    {  
        return mPkgFile->pkg_tell();  
    }  
    //-----------------------------------------------------------------------  
    bool PkgDataStream::eof(void) const 
    {  
        if ( (mPkgFile->GetFilePoint()))  
        {  
            return false;  
        }  
        return ( mPkgFile->pkg_tell() >= static_cast<unsigned long>(mSize) );  
    }  
    //-----------------------------------------------------------------------  
    void PkgDataStream::close(void)  
    {  
        mPkgFile->pkg_file_close();  
    }  
    //-----------------------------------------------------------------------  
    const String& PkgArchiveFactory::getType(void) const 
    {  
        static String name = "Pkg";  
        return name;  
    }  

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/eaglewood2005/archive/2010/01/03/5123803.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值