使用back_insert_device包装vector调用Boost write_xml后vector大小为0的原因咨询
你的vector
v为啥大小是0?问题出在流的缓冲上! 嘿,我来帮你拆解这个问题:你用boost::iostreams::stream配合back_insert_device写入vector,但最终vector是空的,核心原因是流的内部缓冲区没被刷新。
Boost.IOStreams的stream类会把数据先存在自己的缓冲区里,只有当缓冲区满了、你手动刷新,或者流被销毁的时候,才会把数据同步到底层的back_insert_device(也就是你的vector)。而你现在的代码里,调用完write_xml后,流对象还活着,缓冲区里的数据根本没被写到vector里,所以v.size()自然是0。
相比之下,std::stringstream之所以能正常工作,是因为它在析构时会自动触发缓冲区刷新,而且很多操作(比如调用str())也会强制同步缓冲区,所以你看不到这个问题。
两种快速解决方法
方法1:手动刷新并关闭流
在write_xml之后,显式调用flush()和close(),把缓冲区里的所有数据推到vector里:
boost::property_tree::write_xml(os, pt); os.flush(); // 强制把缓冲区数据写入vector os.close(); // 关闭流,确保所有资源都同步
方法2:用局部作用域触发RAII自动清理
把流和sink的定义放到一个局部代码块里,当代码块结束时,这两个对象会被自动销毁,此时流会自动刷新缓冲区并同步数据到vector:
std::vector<char> v; { back_insert_device<std::vector<char>> sink{v}; stream<back_insert_device<std::vector<char>>> os{sink}; boost::property_tree::write_xml(os, pt); } // 这里os和sink被销毁,数据自动写入v
修正后的完整代码示例
这里用方法1的完整代码,你可以直接运行测试:
#include <boost/iostreams/device/array.hpp> #include <boost/iostreams/device/back_inserter.hpp> #include <boost/iostreams/stream.hpp> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> #include <vector> #include <iostream> using namespace boost::iostreams; int main() { boost::property_tree::ptree pt; pt.put("file.name", "testf"); pt.put("file.type", "xml"); pt.put("file.size", 0); std::vector<char> v; back_insert_device<std::vector<char>> sink{v}; stream<back_insert_device<std::vector<char>>> os{sink}; boost::property_tree::write_xml(os, pt); os.flush(); os.close(); std::cout << v.size() << std::endl; // 现在会输出正确的XML数据长度 }
这样修改后,你的vector就能正确接收到XML数据,同时也避免了std::stringstream带来的额外字符串分配开销,完美符合你的需求~
内容的提问来源于stack exchange,提问作者user3472
相关产品推荐
相关产品推荐

