65.9K
CodeProject 正在变化。 阅读更多。
Home

派生自流的Encoder类

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.05/5 (7投票s)

2004年9月2日

2分钟阅读

viewsIcon

37611

downloadIcon

674

如何实现一个从 Xstream 类派生的类,以及如何从中进行序列化。

引言

通常,您希望向流类(istreamostreamiostream)添加特殊功能。 实现此目的的一种方法是创建一个专门的 streambuf 类并重载流基类方法。

一个 Xstream 类构造函数有一个 streambuf 参数,该参数附加到流。 例如,要写入文件,您可以这样做

filebuf fb; 
fb.open ("test.txt",ios::out); 
ostream os(&fb); //... 

但是,如果您的目标不是写入文件,而是写入通用内存缓冲区,则可以这样构造您的 ostream 派生类

class MyStreamBuf : public streambuf { 
// ... you can overload streambuf methods here
}; 
class MyOutputStream : public ostream { 
public: 
MyOutputStream() : ostream(&stBuf) {} 
// ... you can overload ostream methods here
private: 
MyStreamBuf stBuf; 
};

istreamiostream 类也一样。 重载 Xstream 方法允许您创建一个专门的流类。

如果要将基本类型或其他对象序列化为 MyOutputStream,则必须创建一个返回 MyOutputStream 引用对象的 方法,以便您可以编写如下内容

MyOutputStream mos; 
mos << "hello";

现在,我们来看一个示例,将此技术应用于 Encoder 类,其中编码操作可以这样执行

Encoder obj;
obj << "Hello"; //encode the "Hello" string e put it into an Encoder stream
and the decode operation can be performed so
string str;
obj >> str; //decoding in str

使用代码

在这里,我们将看到一个示例,该示例允许通过 ostream 的派生类的运算符 <<>> 来操作字符串。 此外,我们创建一个专门的 streamuf 类,用于编码和解码字符串缓冲区。

在此示例代码中,正如我们之前解释的那样,字符串可以这样编码和解码

Encoder y; 
y << "Hello" //encode a string into a stream 
y >> str;  //decode stream into a string

Encode 方法仅包含字符串中 char 的 ASCII 转换,而 Decode 则反转此操作。

#include <string>
#include <fstream>
#include <iostream> 

using namespace std;

class BufferEncoder: public streambuf {
private:
string buffer; //encoded string
int numCar; //chars number of encoded string
public:

BufferEncoder() : streambuf(), numCar(0) {}
~BufferEncoder() {}

//encode a string and put it into BufferEncoder buffer
void Encode(const string& s){
    char tmp[10];
    for (unsigned int i=0; i< s.length(); ++i){
        itoa(s[i],tmp,10);
        buffer+= (string)tmp + (string)" "; //encode in an ASCII value
        numCar +=strlen(tmp)+1;
    }
}

//decode BufferEncoder buffer and return it into s
void Decode(string& s){
    string decodeStr;
    for (int i=0; i< numCar;++i){
        string tokenStr;
        while ((buffer.at(i) != ' ')&& (buffer.at(i)!='\n') && (i< numCar)){
            tokenStr += buffer.at(i);
            i++;
        }
        int v = atoi(tokenStr.c_str());
        decodeStr += (char) v; //decoded char
    }
    s = decodeStr;
}

//add and end of line into buffer 
void EndOfLine() {
   buffer += '\n';
   numCar ++;
}

//return buffer pointer
char* GetBuffer() {return ((char*) buffer.c_str());}
};

class Encoder : public ostream {
private:
    BufferEncoder myStrBuf; 
public: 
    //constructors
    Encoder(filebuf* fb) : ostream(fb),ios(0) {}
    Encoder() : ostream(&myStrBuf),ios(0) {}

    //endl manipulator serialization
    _Myt& operator<<(_Myt&(__cdecl *_Pfn )(_Myt&) ){
        // call basic_ostream manipulator
        //... no others manipulators than endl
        myStrBuf.EndOfLine();
        return ((*_Pfn)(*this));
    }

    //from Encoder to ostream serialization
    friend ostream& operator<<(ostream & s, Encoder& c) {
        s << c.myStrBuf.GetBuffer();
        return s;
    }

    //from const char* to Encoder serialization
    Encoder& operator<<(const char * s) {
        myStrBuf.Encode(s);
        return *this;
    }

    //from Encoder to string serialization
    Encoder& operator>>(string& s) {
        myStrBuf.Decode(s);
        return *this;
    } 
}; 

int main ()
{
    Encoder y;

    //encoding
    y <<"Hello World!";
    cout <<"ENCODED: "<< y << endl;

    //decoding
    string s ;
    y >> s;
    cout << "DECODED: " << s << endl;
    return 0;
}

关注点

此代码可以帮助您学习如何将对象(基本类型或用户定义)序列化到或从对象流,例如预定义对象 cincout。 实际上,就像一个 istream 对象 cinostream 对象 cout 一样,在 C++ 中,您可以从这些类定义派生和用户定义的对象,并创建到或从这些对象的方法。

历史

  • v 1.1 修复了一些代码样式技巧
  • v 1.0
© . All rights reserved.