c++ - 创建自定义 std::streambuf

标签 c++ file-io stl

我正在定义一个自定义 std::streambuf 类以用于文件 I/O。在这个类中,我正在重载函数 opencloseis_openxsgetnxsputn溢出下溢uflow。然后,我将此缓冲区插入到 std::ifstream 中,如下所示(同样的情况适用于 std::ofstream):

std::ifstream temp;
Filebuffer *buffer = new Filebuffer();
buffer->open(fileName.c_str(), std::ios_base::in | std::ios_base::binary);
temp.basic_ios<char>::rdbuf(buffer);

Filebuffer(我的自定义类)的实现如下:

std::streamsize
Filebuffer::xsputn(const char *s, std::streamsize n)
{
  std::streamsize result = 0;

  if(file && n)
  {
    for(;;)
    {
      size_t buffer_use = this->epptr() - this->pptr();

      if(buffer_use > 0)
      {
        if(static_cast<int>(buffer_use) > n)
        {
          buffer_use = n;
        }

        std::char_traits<char>::copy(this->pptr(), s, buffer_use);

        this->pbump(buffer_use);
        result += buffer_use;
        n -= buffer_use;

        if(n == 0)
        {
          break;
        }

        s += buffer_use;
      }

      this->overflow(static_cast<int>(*s));
    }
  }

  return result;
}

std::streamsize
Filebuffer::xsgetn(char *s, std::streamsize n)
{
  std::streamsize result = 0;

  if(file && n)
  {
    int ch;    do
    {
      size_t buffer_use = this->egptr() - this->gptr();

      if(buffer_use > 0)
      {
        if(static_cast<int>(buffer_use) > n)
        {
          buffer_use = n;
        }

        std::char_traits<char>::copy(s, this->gptr(), buffer_use);

        this->gbump(buffer_use);
        result += buffer_use;
        n -= buffer_use;

        if(n == 0)
        {
          break;
        }

        s += buffer_use;
      }

      ch = this->underflow();
    } while(!(ch == std::char_traits<char>::eof()));
  }

  return result;
}

int
Filebuffer::underflow()
{
  if(file)
  {
    nullify_put_area(); //clears write buffer

    if(!buffer) //allocated in open()
    {
      int value = ungetc(fgetc(file), file);

      if(value == EOF)
      {
        return std::char_traits<char>::eof();
      }

      return value;
    }

    char *begin = buffer;
    char *end = buffer + bufferSize - 1; //bufferSize set to 4 KB
    char *next = end;

    if(this->gptr() < this->egptr())
    {
      size_t buffer_use = this->egptr() - this->gptr();

      memmove(begin, next, buffer_use);
      begin += buffer_use;
    }

    setg(begin, begin, begin);


    size_t m = (bufferSize - 1 - (begin - this->eback()));

    if(m > 0)
    {
      size_t status = fread(begin, 1, m, file);

      if(status == 0)
      {
        return std::char_traits<char>::eof();
      }

      setg(this->eback(), this->gptr(), begin + status);
    }

    return static_cast<int>(*this->gptr());
  }

  return std::char_traits<char>::eof();
}

int
Filebuffer::uflow()
{
  if(!file)
  {
    return std::char_traits<char>::eof();
  }

  int ch = underflow();

  if(ch != std::char_traits<char>::eof())
  {
    if(buffer)
    {
      this->gbump(1);
    }

    else
    {
      fgetc(file);
    }
  }

  return ch;
}

int
Filebuffer::overflow(int c)
{
  if(!file)
  {
    return std::char_traits<char>::eof();
  }

  const char *begin = this->pbase();
  char *next = this->pptr();

  if(buffer)
  {
    setp(buffer, buffer + bufferSize - 1);
  }

  nullify_get_area(); //clears read buffer

  char temp;
  if(c == std::char_traits<char>::eof())
  {
    c = std::char_traits<char>::not_eof(std::char_traits<char>::eof());
  }

  else
  {
    if(!next)
    {
      begin = next = &temp;
    }

    assert(next == &temp || buffer <= next);
    assert(next == &temp || next < buffer + bufferSize);
    *next++ = static_cast<char>(c);
  }

  if(begin != next)
  {
    if(begin == &temp)
    {
      fputc(temp, file);
      return c;
    }

    size_t n = next - begin;
    size_t status = fwrite(begin, 1, n, file);

    if(status != n)
    {
      return std::char_traits<char>::eof();
    }

    return c;
  }

  return std::char_traits<char>::eof();
}

不幸的是,每当我使用(例如)temp >> readVar; 时,它都不会使用我的任何重载函数 - 调用堆栈显示调用了 STL 原始实现 - 相反,只是读入垃圾。每this question ,我需要为 ofstream 定义 overflow(并且可能为 ifstream 定义 underflow),我已经完成了。我是否正确定义了 xsputnxsgetn?为什么我的重载函数没有被调用?

最佳答案

似乎尝试使用 std::ifstream 执行此操作将不起作用,我需要更改它 std::istream。进行此更改后,将调用重载函数并且一切正常。

关于c++ - 创建自定义 std::streambuf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30853370/

相关文章:

c++ - 移动到文件中的下一行 C++

c++ - 按值与按引用的 STL 容器对象

c++ - 需要澄清 C++ 模板格式

c++ - 包含一批到 "Include Additional Directories"Visual C++ 的库和目录路径的任何方法

c++ - move 语义 == 自定义交换功能已过时?

iphone - iPhone-如何从设备读取书籍文件

c++ - 索引和插入调用之间的 std::map 区别

c++ - 如何在 C 中找到可执行文件的位置?

c++ - 栈有什么用?为什么它们在 C++ 中?

java - JFileChooser.showSaveDialog() 没有出现