自定义 std::fstream,std::filebuf 的溢出和下溢函数未为每个字符调用
custom std::fstream, std::filebuf's overflow and underflow function not invoked for every character
我正在尝试制作一个自定义std::fstream,它将在读取时对数据进行编码/解码。
template <class T>
class _filebuf : public std::filebuf {
public:
using transform_type = T;
int_type underflow() override {
auto c = std::filebuf::underflow();
return c < 0 ? c : transform.decode(c);
}
int_type overflow(int_type c) override {
return c < 0 ? c : std::filebuf::overflow(transform.encode(c));
}
private:
transform_type transform;
};
template <class T>
class _fstream : public std::iostream {
public:
using buffer_type = _filebuf<T>;
explicit _fstream(const std::string& path, std::ios::openmode openmode)
: std::iostream(0)
{
this->init(&buffer);
buffer.open(path, openmode);
}
private:
buffer_type buffer;
};
下面是一个使用示例:
class _transform {
public:
template <class T>
T encode(T value) const {
return value - 1;
}
template <class T>
T decode(T value) const {
return value + 1;
}
};
int main() {
_fstream<_transform> ofs("test.txt", std::ios::out | std::ios::trunc);
ofs << "ABC"; // outputs "@BC" to the file (@ is 64 in ASCII, so only first character encoded properly)
_fstream<_transform> ifs("test.txt", std::ios::in);
std::string s;
ifs >> s; // inputs "ABC" when "@BC" was in the file so again only first character is decoded
// ...
};
经过我自己的研究,我发现">溢出"函数在这个过程中被调用了两次(65和-1,其中-1可能是EOF(,"下溢">也被调用了两次(64和-1(。由于其他字符不会丢失,因此可能会在不调用这些函数的情况下以某种方式处理它们。
为什么会发生这种情况以及如何改变它?
std::streambuf<CharT,Traits>::underflow
确保get区域中至少有一个字符可用,std::filebuf
的有效实现将始终尝试将完整的缓冲区字符读取到get区域中。除非您寻求流,否则underflow
不会再次调用,直到对sgetn
/xsgetn
或sbumpc
的调用清空获取区域
我认为您可能会更成功地包装而不是扩展文件缓冲区。
Boost iostreams 使写入流过滤器变得更加简单。
相关文章:
- 带有指定长度字符* 参数的 std::regex_search 在 VS2017 中不起作用?
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 从 std::vector<无符号字符>切片中提取 int?
- 字符转换功能 std::isupper() & std::islower() C++17
- 将无符号字符的向量存储在数组中会给我 std::bad_alloc
- 为什么 std::string_view 比常量字符*快?
- std::stringstream 返回字符 *
- 如何将带有十六进制值的 std::string 转换为 std::vector<无符号字符>
- 自定义 std::fstream,std::filebuf 的溢出和下溢函数未为每个字符调用
- 在 c++ 中以十六进制格式打印无符号字符(BYTE).使用 std::cout
- 在 std::vector<无符号字符中存储任意数据的方法>
- 为什么从 std::cin 读取输入后右括号字符的值有时不是")"?
- "std::string"是否将其字符作为签名字符在内部存储?
- std::stoi 只转换前几个字符
- std::可选实现为联合与字符[]/aligned_storage
- C++ 无法将 std::vector<BYTE> 转换为字符串或字符数组
- 如何使用 std::copy 当类有"无符号字符和运算符[]"时
- C++ 从 std::string 中删除所有非数字字符
- 我可以得到一个字符 * 到一个 std::sregex_iterator 匹配 str() 吗?
- 使用 .data() 将字符数组转换为 std::string 不会转换整个数组