我正在定义一个用于文件I / O的自定义std::streambuf
类。在本课程中,我正在重载函数open
,close
,is_open
,xsgetn
,xsputn
,overflow
,underflow
和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原始实现 - 而只是简单地读取垃圾。根据{{3}},我需要为overflow
定义ofstream
(可能是underflow
ifstream
),我已经完成了。我是否正确定义了xsputn
和xsgetn
?为什么我的重载函数没有被调用?
答案 0 :(得分:1)
似乎尝试使用std::ifstream
执行此操作无效,我需要更改std::istream
。一旦我做了这个改变,就会调用重载的函数,一切正常。