找回密码
 register

QQ登录

只需一步,快速开始

查看: 229|回复: 0

[游戏教程] 天龙八部二进制文件 读写序列化类

[复制链接]

[游戏教程] 天龙八部二进制文件 读写序列化类

[复制链接]
  • 打卡等级:热心大叔
  • 打卡总天数:95
  • 打卡月天数:18
  • 打卡总奖励:95
  • 最近打卡:2025-01-20 23:11:04
Waylee

主题

0

回帖

1万

积分

仙帝

积分
12398
Waylee 2024-2-4 02:22 | 显示全部楼层 |阅读模式

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?register

×

可以方便地实现天龙二进制的读和写

首先是序列类

#ifndef __CORE_SERIALIZER_UTIL_H__   
#define __CORE_SERIALIZER_UTIL_H__   
  
#include <OgreString.h>   
#include <OgreDataStream.h>   
using namespace Ogre;  
  
namespace Core  
{  
    // Endian routines   
    extern void flipToLittleEndian(void* pData, size_t size, size_t count = 1);  
    extern void flipFromLittleEndian(void* pData, size_t size, size_t count = 1);  
  
    extern void flipEndian(void * pData, size_t size, size_t count);  
    extern void flipEndian(void * pData, size_t size);  
  
    // Writer   
    class Writer   
    {  
    public:  
        virtual ~Writer() {}  
  
        void writeFloats(const float* pFloat, size_t count = 1);  
        void writeFloats(const double* pDouble, size_t count = 1);  
        void writeShorts(const uint16* pShort, size_t count = 1);  
        void writeInts(const uint32* pInt, size_t count = 1);  
        void writeBools(const bool* pBool, size_t count = 1);  
  
        void writeString(const String& string);  
  
        void writeObject(const Ogre::Vector3& v);  
        void writeObject(const Ogre:uaternion& q);  
  
        void writeData(const void* data, size_t size);  
  
    protected:  
        virtual void _write(const void* buf, size_t size, size_t count) = 0;  
    };  
  
    // Reader   
    class Reader   
    {  
    public:  
        virtual ~Reader() {}  
  
        void readFloats(float* pFloat, size_t count = 1);  
        void readFloats(double* pDouble, size_t count = 1);  
        void readShorts(uint16* pShort, size_t count = 1);  
        void readInts(uint32* pInt, size_t count = 1);  
        void readBools(bool* pBool, size_t count = 1);  
  
        String readString(void);  
        String readString(size_t numChars);  
  
        void readObject(Ogre::Vector3& v);  
        void readObject(Ogre:uaternion& q);  
  
        void readData(void* data, size_t size);  
  
    protected:  
        virtual void _read(void* buf, size_t size, size_t count) = 0;  
    };  
  
    // FileWriter   
    class FileWriter : public Writer   
    {  
    private:  
        FileWriter(const FileWriter&);  
        FileWriter& operator= (const FileWriter&);  
  
    public:  
        explicit FileWriter(FILE* file, bool adopts = false)  
            : mFile(file)  
            , mAdopts(adopts)  
        {  
        }  
  
        explicit FileWriter(const String& filename)  
            : mFile(fopen(filename.c_str(), "wb"))  
            , mAdopts(true)  
        {  
        }  
  
        ~FileWriter()  
        {  
            if (mAdopts && mFile)  
                fclose(mFile);  
        }  
  
        FILE* getFile(void) const  
        {  
            return mFile;  
        }  
  
    protected:  
        FILE* mFile;  
        bool mAdopts;  
  
        void _write(const void* buf, size_t size, size_t count);  
    };  
  
    // DataStreamReader   
    class DataStreamReader : public Reader   
    {  
    private:  
        DataStreamReader(const DataStreamReader&);  
        DataStreamReader& operator= (const DataStreamReader&);  
  
    public:  
        explicit DataStreamReader(Ogre:ataStreamPtr& stream)  
            : mStream(stream)  
        {  
        }  
  
        Ogre:ataStreamPtr& getStream(void)  
        {  
            return mStream;  
        }  
  
    protected:  
        Ogre:ataStreamPtr mStream;  
  
        void _read(void* buf, size_t size, size_t count);  
    };  
  
}  
  
#endif  

#include "CoreSerializerUtil.h"   
  
#include <OgreDataStream.h>   
#include <OgreVector3.h>   
#include <OgreQuaternion.h>   
#include <OgreException.h>   
  
namespace Core  
{  
  
    //--------------------------------------------------------------------------------------------   
    void flipToLittleEndian(void* pData, size_t size, size_t count)  
    {  
#   if OGRE_ENDIAN == OGRE_ENDIAN_BIG   
        flipEndian(pData, size, count);  
#   endif   
    }  
  
    //--------------------------------------------------------------------------------------------   
    void flipFromLittleEndian(void* pData, size_t size, size_t count)  
    {  
#   if OGRE_ENDIAN == OGRE_ENDIAN_BIG   
        flipEndian(pData, size, count);  
#   endif   
    }  
  
    //--------------------------------------------------------------------------------------------   
    void flipEndian(void * pData, size_t size, size_t count)  
    {  
        for(size_t index = 0; index < count; index++)  
        {  
            flipEndian((void *)((int)pData + (index * size)), size);  
        }  
    }  
  
    //--------------------------------------------------------------------------------------------   
    void flipEndian(void * pData, size_t size)  
    {  
        char swapByte;  
        for(size_t byteIndex = 0; byteIndex < size/2; byteIndex++)  
        {  
            swapByte = *(char *)((int)pData + byteIndex);  
            *(char *)((int)pData + byteIndex) = *(char *)((int)pData + size - byteIndex - 1);  
            *(char *)((int)pData + size - byteIndex - 1) = swapByte;  
        }  
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeFloats(const float* pFloat, size_t count)  
    {  
#   if OGRE_ENDIAN == OGRE_ENDIAN_BIG   
        float * pFloatToWrite = (float *)malloc(sizeof(float) * count);  
        memcpy(pFloatToWrite, pFloat, sizeof(float) * count);  
  
        flipToLittleEndian(pFloatToWrite, sizeof(float), count);  
        _write(pFloatToWrite, sizeof(float), count);  
  
        free(pFloatToWrite);  
#   else   
        _write(pFloat, sizeof(float), count);  
#   endif   
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeFloats(const double* pDouble, size_t count)  
    {  
        // Convert to float, then write   
        float* tmp = new float[count];  
        for (size_t i = 0; i < count; ++i)  
        {  
            tmp[i] = static_cast<float>(pDouble[i]);  
        }  
#   if OGRE_ENDIAN == OGRE_ENDIAN_BIG   
        flipToLittleEndian(tmp, sizeof(float), count);  
        _write(tmp, sizeof(float), count);  
#   else   
        _write(tmp, sizeof(float), count);  
#   endif   
        delete [] tmp;  
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeShorts(const uint16* pShort, size_t count)  
    {  
#   if OGRE_ENDIAN == OGRE_ENDIAN_BIG   
        uint16 * pShortToWrite = (uint16 *)malloc(sizeof(uint16) * count);  
        memcpy(pShortToWrite, pShort, sizeof(uint16) * count);  
  
        flipToLittleEndian(pShortToWrite, sizeof(uint16), count);  
        _write(pShortToWrite, sizeof(uint16), count);  
  
        free(pShortToWrite);  
#   else   
        _write(pShort, sizeof(uint16), count);  
#   endif   
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeInts(const uint32* pInt, size_t count)  
    {  
#   if OGRE_ENDIAN == OGRE_ENDIAN_BIG   
        uint32 * pIntToWrite = (uint32 *)malloc(sizeof(uint32) * count);  
        memcpy(pIntToWrite, pInt, sizeof(uint32) * count);  
  
        flipToLittleEndian(pIntToWrite, sizeof(uint32), count);  
        _write(pIntToWrite, sizeof(uint32), count);  
  
        free(pIntToWrite);  
#   else   
        _write(pInt, sizeof(uint32), count);  
#   endif   
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeBools(const bool* pBool, size_t count)  
    {  
        // no endian flipping for 1-byte bools   
        // XXX Nasty Hack to convert to 1-byte bools   
#   if OGRE_PLATFORM == OGRE_PLATFORM_APPLE   
        char * pCharToWrite = (char *)malloc(sizeof(char) * count);  
        for(int i = 0; i < count; i++)  
        {  
            *(char *)(pCharToWrite + i) = *(bool *)(pBool + i);  
        }  
  
        _write(pCharToWrite, sizeof(char), count);  
  
        free(pCharToWrite);  
#   else   
        _write(pBool, sizeof(bool), count);  
#   endif   
  
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeString(const String& string)  
    {  
        uint32 numChars = string.length();  
        writeInts(&numChars);  
        _write(string.c_str(), sizeof(String::value_type), numChars);  
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeObject(const Ogre::Vector3& v)  
    {  
        writeFloats(&v.x);  
        writeFloats(&v.y);  
        writeFloats(&v.z);  
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeObject(const Ogre:uaternion& q)  
    {  
        writeFloats(&q.x);  
        writeFloats(&q.y);  
        writeFloats(&q.z);  
        writeFloats(&q.w);  
    }  
  
    //---------------------------------------------------------------------   
    void Writer::writeData(const void* data, size_t size)  
    {  
        _write(data, size, 1);  
    }  
  
    //---------------------------------------------------------------------   
    void Reader::readFloats(float* pFloat, size_t count)  
    {  
        _read(pFloat, sizeof(float), count);  
        flipFromLittleEndian(pFloat, sizeof(float), count);  
    }  
  
    //---------------------------------------------------------------------   
    void Reader::readFloats(double* pDouble, size_t count)  
    {  
        // Read from float, convert to double   
        float* tmp = new float[count];  
        float* ptmp = tmp;  
        _read(tmp, sizeof(float), count);  
        flipFromLittleEndian(tmp, sizeof(float), count);  
        // Convert to doubles (no cast required)   
        while (count--)  
        {  
            *pDouble++ = *ptmp++;  
        }  
        delete [] tmp;  
    }  
  
    //---------------------------------------------------------------------   
    void Reader::readShorts(uint16* pShort, size_t count)  
    {  
        _read(pShort, sizeof(uint16), count);  
        flipFromLittleEndian(pShort, sizeof(uint16), count);  
    }  
  
    //---------------------------------------------------------------------   
    void Reader::readInts(uint32* pInt, size_t count)  
    {  
        _read(pInt, sizeof(uint32), count);  
        flipFromLittleEndian(pInt, sizeof(uint32), count);  
    }  
  
    //---------------------------------------------------------------------   
    void Reader::readBools(bool* pBool, size_t count)  
    {  
        //XXX Nasty Hack to convert 1 byte bools to 4 byte bools   
#   if OGRE_PLATFORM == OGRE_PLATFORM_APPLE   
        char * pTemp = (char *)malloc(1*count); // to hold 1-byte bools   
        _read(pTemp, sizeof(char), count);  
        for(int i = 0; i < count; i++)  
            *(bool *)(pBool + i) = *(char *)(pTemp + i);  
  
        free (pTemp);  
#   else   
        _read(pBool, sizeof(bool), count);  
#   endif   
        //no flipping on 1-byte datatypes   
    }  
  
    //---------------------------------------------------------------------   
    String Reader::readString(size_t numChars)  
    {  
        String str(numChars, '/0');  
        _read(const_cast<String::value_type*>(str.data()), sizeof(String::value_type), numChars);  
        return str;  
    }  
    //---------------------------------------------------------------------   
    String Reader::readString(void)  
    {  
        uint32 numChars;  
        readInts(&numChars);  
        return readString(numChars);  
    }  
    //---------------------------------------------------------------------   
    void Reader::readObject(Ogre::Vector3& v)  
    {  
        readFloats(&v.x);  
        readFloats(&v.y);  
        readFloats(&v.z);  
    }  
    //---------------------------------------------------------------------   
    void Reader::readObject(Ogre:uaternion& q)  
    {  
        readFloats(&q.x);  
        readFloats(&q.y);  
        readFloats(&q.z);  
        readFloats(&q.w);  
    }  
    //---------------------------------------------------------------------   
    void Reader::readData(void* data, size_t size)  
    {  
        _read(data, size, 1);  
    }  
  
    //--------------------------------------------------------------------------------------------   
    void FileWriter::_write(const void* buf, size_t size, size_t count)  
    {  
        if (fwrite(buf, size, count, mFile) != count)  
        {  
            OGRE_EXCEPT(Ogre::Exception::ERR_CANNOT_WRITE_TO_FILE,  
                "Can't write data to file",  
                "FileWriter::_write");  
        }  
    }  
  
    //--------------------------------------------------------------------------------------------   
    void DataStreamReader::_read(void* buf, size_t size, size_t count)  
    {  
        if (mStream->read(buf, size * count) != size * count)  
        {  
            OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR,  
                "Can't read data from stream",  
                "DataStreamReader::_read");  
        }  
    }  
}  


怎么用呢,举个例子,我们读取和写入高度图

namespace Core

{       const uint32 TERRAIN_HEIGHTMAP_MAGIC = 'FEHM';       const uint32 TERRAIN_HEIGHTMAP_VERSION = 0x00100000;          //------------------------------------------------------------------------------------------------        void TerrainData::_loadHeightmap(const String& filename, const String& type, const String& groupName)       {           // 分配buffer            mHeightmap.resize((mXSize + 1) * (mZSize + 1));              if (filename.empty())           {               std::fill(mHeightmap.begin(), mHeightmap.end(), (Real)0);           }           else if (type == "image")           {               // 省略            }           else if (type == "standard")           {               Ogre:ataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(filename, groupName);               DataStreamReader reader(stream);                  // 文件头校验                uint32 header[4];               reader.readInts(header, 4);               if (header[0] != TERRAIN_HEIGHTMAP_MAGIC)               {                   // 异常                }               if (header[1] != TERRAIN_HEIGHTMAP_VERSION)               {                   // 异常                }               if (header[2] != mXSize+1 || header[3] != mZSize+1)               {                   // 异常                }                  // 读取高度数据                reader.readFloats(&mHeightmap[0], mHeightmap.size());                  // 文件尾校验                if (stream->tell() != stream->size())               {                   // 异常                }           }           else           {               assert(type == "raw");               // 省略            }       }          //-----------------------------------------------------------------------------------------------------------------        void TerrainData::_saveHeightmap(const String& filename) const       {           FileWriter writer(filename);              // 写文件头            uint32 header[4];           header[0] = TERRAIN_HEIGHTMAP_MAGIC;           header[1] = TERRAIN_HEIGHTMAP_VERSION;           header[2] = mXSize + 1;           header[3] = mZSize + 1;           writer.writeInts(header, 4);              // 写数据            writer.writeFloats(&mHeightmap[0], mHeightmap.size());       }   }  

您需要登录后才可以回帖 登录 | register

本版积分规则

雪舞知识库 | 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 |天天打卡

GMT+8, 2025-1-21 01:52 , Processed in 0.096935 second(s), 7 queries , Redis On.

Powered by XueWu Licensed

Copyright © Tencent Cloud.

快速回复 返回顶部 返回列表