如何在C++; 我目前正在学习C++(来自java),我正在尝试理解C++中如何正确使用IO流。p>

如何在C++; 我目前正在学习C++(来自java),我正在尝试理解C++中如何正确使用IO流。p>,c++,iostream,C++,Iostream,假设我有一个Image类,它包含图像的像素,我重载了提取操作符以从流中读取图像: istream& operator>>(istream& stream, Image& image) { // Read the image data from the stream into the image return stream; } 现在我能读到这样的图像: Image image; ifstream file("somepic.img"); fi

假设我有一个
Image
类,它包含图像的像素,我重载了提取操作符以从流中读取图像:

istream& operator>>(istream& stream, Image& image)
{
    // Read the image data from the stream into the image
    return stream;
}
现在我能读到这样的图像:

Image image;
ifstream file("somepic.img");
file >> image;
InputStream stream = new CompressedInputStream(new FileInputStream("somepic.imgz"));
image.read(stream);
class compressbuf
    : public std::streambuf {
    std::streambuf* sbuf_;
    char*           buffer_;
    // context for the compression
public:
    compressbuf(std::streambuf* sbuf)
        : sbuf_(sbuf), buffer_(new char[1024]) {
        // initialize compression context
    }
    ~compressbuf() { delete[] this->buffer_; }
    int underflow() {
        if (this->gptr() == this->egptr()) {
            // decompress data into buffer_, obtaining its own input from
            // this->sbuf_; if necessary resize buffer
            // the next statement assumes "size" characters were produced (if
            // no more characters are available, size == 0.
            this->setg(this->buffer_, this->buffer_, this->buffer_ + size);
        }
        return this->gptr() == this->egptr()
             ? std::char_traits<char>::eof()
             : std::char_traits<char>::to_int_type(*this->gptr());
    }
};
但是现在我想使用相同的提取操作符从自定义流读取图像数据。假设我有一个文件,其中包含压缩格式的图像。因此,我可能希望实现自己的输入流,而不是使用ifstream。至少在Java中我会这样做。在Java中,我将编写一个自定义类来扩展
InputStream
类,并实现
intread()
方法。所以这很容易。用法如下所示:

Image image;
ifstream file("somepic.img");
file >> image;
InputStream stream = new CompressedInputStream(new FileInputStream("somepic.imgz"));
image.read(stream);
class compressbuf
    : public std::streambuf {
    std::streambuf* sbuf_;
    char*           buffer_;
    // context for the compression
public:
    compressbuf(std::streambuf* sbuf)
        : sbuf_(sbuf), buffer_(new char[1024]) {
        // initialize compression context
    }
    ~compressbuf() { delete[] this->buffer_; }
    int underflow() {
        if (this->gptr() == this->egptr()) {
            // decompress data into buffer_, obtaining its own input from
            // this->sbuf_; if necessary resize buffer
            // the next statement assumes "size" characters were produced (if
            // no more characters are available, size == 0.
            this->setg(this->buffer_, this->buffer_, this->buffer_ + size);
        }
        return this->gptr() == this->egptr()
             ? std::char_traits<char>::eof()
             : std::char_traits<char>::to_int_type(*this->gptr());
    }
};
因此,使用相同的模式可能我想在C++中实现这一点:

Image image;
ifstream file("somepic.imgz");
compressed_stream stream(file);
stream >> image;
但也许这是错误的方式,我不知道。扩展
istream
类看起来相当复杂,经过一些搜索,我找到了一些关于扩展
streambuf
的提示。但对于如此简单的任务来说,这看起来非常复杂

<>在C++中,实现自定义输入输出流(或流式Buffs)的最好方法是什么? 解决方案 一些人建议根本不要使用iostreams,而是使用迭代器、boost或自定义IO接口。这些可能是有效的选择,但我的问题是关于iostreams的。接受的答案产生了下面的示例代码。为了便于阅读,没有头/代码分离,并且导入了整个std名称空间(我知道这在实际代码中是一件坏事)

本例是关于读取和写入垂直xor编码图像的。格式很简单。每个字节代表两个像素(每像素4位)。每一行与前一行异或。这种编码为压缩图像做准备(通常会产生大量的0字节,更容易压缩)

#包括
#包括
使用名称空间std;
/***vxor_streambuf类******************************************/
vxor_streambuf类:公共streambuf
{
公众:
vxor_streambuf(streambuf*缓冲区,常量整数宽度):
缓冲器(缓冲器),
尺寸(宽度/2)
{
上一行=新字符[大小];
memset(上一行,0,大小);
当前_行=新字符[大小];
setg(0,0,0);
setp(当前_线,当前_线+尺寸);
}
虚拟~vxor_streambuf()
{
sync();
删除[]上一行;
删除[]当前_行;
}
虚拟流BUF::int_类型下溢()
{
//从原始缓冲区读取行
streamsize读取=缓冲区->sgetn(当前行,大小);
if(!read)返回字符类型::eof();
//做垂直异或解码
对于(int i=0;isputn(当前_行,写入);
if(write!=write)返回字符类型::eof();
}
setp(当前_线,当前_线+尺寸);
如果(!traits_type::eq_int_type(值,traits_type::eof()))sputc(值);
返回特征\类型::非\ eof(值);
};
虚拟整数同步()
{
streambuf::int_type result=this->overflow(traits_type::eof());
buffer->pubsync();
返回traits_type::eq_int_type(result,traits_type::eof())?-1:0;
}
私人:
streambuf*缓冲区;
整数大小;
字符*上一行;
字符*当前_行;
};
/***vxor_istream类********************************************/
vxor_类istream:公共istream
{
公众:
vxor_istream(istream&stream,常量整数宽度):
istream(新vxor_streambuf(stream.rdbuf(),width)){
虚拟~vxor_istream()
{
删除rdbuf();
}
};
/***vxor_ostream类********************************************/
vxor_类ostream:公共ostream
{
公众:
vxor_ostream(ostream&stream,常量整数宽度):
ostream(新vxor_streambuf(stream.rdbuf(),width)){
虚拟~vxor_ostream()
{
删除rdbuf();
}
};
/***主要试验方法**********************************************/
int main()
{
//读取数据
ifstream INFLE(“test.img”);
vxor_istream in(infle,288);
字符数据[144*128];
in.读取(数据,144*128);
infle.close();
//写入数据
排液管(“test2.img”);
vxor_ostream out(输出文件,288);
out.write(数据,144*128);
out.flush();
outfile.close();
返回0;
}

不要,除非你想死于可怕的设计。iostream是标准库中最差的组件,甚至比locale还要差。迭代器模型更有用,可以用ISTRAMAMIATER来从流转换为迭代器。< /P> < P>在C++中创建新流的正确方法是从<代码> STD::StRuBFF < /C> >重写<代码>下溢()/<代码>读取操作和<代码>溢出()/<代码>和<代码>同步()写入操作。出于您的目的,您需要创建一个过滤流缓冲区,该缓冲区将另一个流缓冲区(可能还有一个流,可以使用
rdbuf()
)从中提取流缓冲区)作为参数,并根据该流缓冲区实现自己的操作

基本法
class Input {
 public:
  virtual void read(char *buffer, size_t size) = 0;
  // ...
};