Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在io.h中定义的写操作中添加写缓冲区_C++_Buffer - Fatal编程技术网

C++ 如何在io.h中定义的写操作中添加写缓冲区

C++ 如何在io.h中定义的写操作中添加写缓冲区,c++,buffer,C++,Buffer,我在io.h中使用write(fd、buffer、count)将缓冲区写入文件描述符 现在我发现了巨大的性能问题,因为每次我调用“write”时,它都会执行IO操作 我想在将内容写入文件之前添加一个缓冲区 最好的方法是什么 我搜索并找到了这个: http://www.java2s.com/Tutorial/Cpp/0240__File-Stream/filedescriptoroutbuffer.htm 我应该使用这种方法并集成到代码中吗?这是我应该采取的好方法吗 但在它里面,我看不到如何定义缓

我在io.h中使用write(fd、buffer、count)将缓冲区写入文件描述符

现在我发现了巨大的性能问题,因为每次我调用“write”时,它都会执行IO操作

我想在将内容写入文件之前添加一个缓冲区

最好的方法是什么

我搜索并找到了这个:

http://www.java2s.com/Tutorial/Cpp/0240__File-Stream/filedescriptoroutbuffer.htm

我应该使用这种方法并集成到代码中吗?这是我应该采取的好方法吗

但在它里面,我看不到如何定义缓冲区大小

以下是最终代码:

class fdoutbuf : public std::streambuf {
    protected:
        enum { size = 4096 };
        int fd;    // file descriptor
        char buf_[size];
    public:
    // constructor
    fdoutbuf (int _fd) : fd(_fd) {
        setp(this->buf_, this->buf_ + size - 1);
    }
    protected:
    // write one character
    virtual int overflow (int c){
        if (c != EOF) {
            char z = c;
            *this->pptr() = z;
            this->pbump(1);
        }
        return this->sync() == -1? EOF: c;
    }
    virtual int sync(){
         if (this->pbase() == this->pptr()) {
            return 0;
        }
        int count(this->pptr() - this->pbase());
        int rc = write(fd, this->buf_, count);
        this->setp(this->buf_, this->buf_ + size - 1);
        return count == rc? 0: -1;
    }
};


class fdostream : public std::ostream {
  protected:
    fdoutbuf buf;
  public:
    fdostream (int fd) : std::ostream(0), buf(fd) {
        rdbuf(&buf);
    }
};

如果你用C++编写,你可以尝试使用<代码> STL< /COD>和<代码> /COD>输出到文件中。它已内置缓冲区,不存在速度问题。

< P>如果你用C++编写,你可以尝试使用<代码> STL< /COD>和<代码> /COD>输出到文件中。它已经内置了缓冲区,并且在速度上没有这样的问题。

创建缓冲基础设施不是真正的火箭科学,但也不是完全微不足道的。就我个人而言,我只需要创建一个派生自
std::streambuf
的类,或者使用流缓冲区抽象,或者使用流(可能我会使用后者,并接受大多数实现带来的较小性能影响)。这样做的工作相当简单(仅用于写作):

似乎有必要解释一下上面的流缓冲区实际上做了什么(考虑到下面冗长的讨论)。因此,这里有一个细分:

  • 代码使用固定大小的缓冲区。这只是为了减少示例的大小:可以轻松扩展为使用分配的可变大小缓冲区,例如使用
    std::vector
    :大小将成为默认参数
  • 函数
    setp()
    设置流缓冲区使用的缓冲区,由三个指针组成:
    • pbase()
      是缓冲区的开始,即
      setp()的第一个参数
    • epptr()
      是缓冲区的结尾,即
      setp()的第二个参数
    • pptr()
      设置为与
      pbase()
      相同的值,但它是实际移动以指示下一个字符位置的指针。如果写入字符时这是
      epptr()
      ,则调用
      overflow()
  • 虚拟函数
    overflow()
    可能具有导致缓冲区溢出的字符。除非用户代码使用参数
    eof()
    调用该函数,否则标准库调用该函数时就是这种情况。为了处理这个额外的字符,在可用空间不足的情况下,给缓冲区一个元素:可以在实际写入缓冲区之前将字符追加到缓冲区
  • 继承自
    std::streambuf
    traits_type
    定义了许多函数来确定字符的属性。检查传递给
    overflow()
    的参数时,将使用函数
    eq\u int\u type()
    ,该函数将与流的整数类型的对象进行相等性比较。它将
    overflow()
    的参数与指示使用
    eof()
    获得的无效字符的值进行比较。traits类型的所有成员都是
    static
    typedef
    s,即不需要使用此类型的对象。当使用
    std::basic\u streambuf
    的不同模板实例化时,使用
    traits\u type
    非常重要
  • 虽然缓冲区通常是
    pbase()
    epptr()
    的,在这两个端点之间有
    pptr()
    ,但是
    pptr()
    可以使用
    pbump(n)
    移动到
    epptr()
    之外:此函数只是将
    n
    添加到
    pptr()
    。这用于在调用
    sync()
    之前将currencnt字符放入缓冲区,后者只写入缓冲区的内容并重置它
  • 如果函数失败,
    overflow()
    的返回为
    eof()
    。成功执行时,函数返回与
    eof()
    不同的内容,通常使用作为参数传递的字符。由于参数可能是
    eof()
    ,仅返回参数是不够的,但是:如果它是
    eof()
    ,则需要将此值转换为其他有用的值,而这正是
    not_eof()
    所做的:除非参数是
    eof(),否则它将返回参数
    在这种情况下,它会返回一些合适的其他值
  • 虚拟函数
    sync()
    负责刷新缓冲区。在这种情况下,首先检查是否有需要执行的操作,如果有,则写入缓冲区的内容。这个函数实际上没有任何技巧,尽管我想如果
    write()
    失败,即返回的字符数少于缓冲区中的字符数,那么正确的技巧会更加小心。这个版本只是假装可以释放无法写入的字符,尽管它会指示错误
  • 该函数仍然使用在缓冲区末尾保留一个字符空间的相同方法重置缓冲区
  • 失败时,函数返回
    -1
    ,成功时返回
    0
    。别耍花招

创建缓冲基础设施并不是真正的火箭科学,但也不是一件小事。就我个人而言,我只需要创建一个派生自
std::streambuf
的类,或者使用流缓冲区抽象,或者使用流(可能我会使用后者,并接受大多数实现带来的较小性能影响)。这样做的工作相当简单(仅用于写作):

似乎有必要解释一下上面的流缓冲区实际上做了什么(考虑到下面冗长的讨论)
struct fdbuf: std::streambuf {
    enum { size = 4096 };
    fdbuf(int fd): fd_(fd) { this->setp(this->buf_, this->buf_ + size - 1); }
    int overflow(int c) {
        if (!traits_type::eq_int_type(c, traits_type::eof())) {
            *this->pptr() = traits_type::to_char_type(c);
            this->pbump(1);
        }
        return this->sync() == -1? traits_type::eof(): traits_type::not_eof(c);
    }
    int sync() {
        if (this->pbase() == this->pptr()) {
            return 0;
        }
        int count(this->pptr() - this->pbase());
        int rc = write(this->fd_, this->buf_, count);
        this->setp(this->buf_, this->buf_ + size - 1);
        return count == rc? 0: -1;
    }
    int  fd_;
    char buf_[size];
};