使用 boost 将 C *FILE 转换为 C++ iostream

Sim*_*her 4 c++ boost iostream boost-iostreams

我对 C++ 相当陌生,想要将 *FILE(例如由 popen() 返回)转换为 iostream,以便与 getline 等函数一起使用。我找到了以下代码http://fw-geekycoder.blogspot。 co.za/2011/06/how-to-convert-c-file-to-c-iostream.html,以及来自很多地方的类似代码,但编译器抱怨boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd);boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd);

\n\n
#include <iostream>\n#include <cstdio>\n#include <unistd.h>\n#include <boost/iostreams/device/file_descriptor.hpp>\n#include <boost/iostreams/stream.hpp>\n\nvoid write() {\n    FILE* fp = fopen("whatever.txt", "w");\n    if (fp == NULL) {\n        perror("fopen error");\n    }\n    int fd = fileno(fp);\n    boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> bis(fd);\n    std::ostream os(&bis);\n    os << "Hello World!" << std::endl;\n\n    fclose(fp);\n}\n\nvoid read() {\n    FILE* fp = fopen("whatever.txt", "r");\n    if (fp == NULL) {\n        perror("fopen error");\n    }\n    int fd = fileno(fp);\n    boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> bis(fd);\n    std::istream is(&bis);\n    while (is) {\n        std::string line;\n        std::getline(is, line);\n        std::cout << line << std::endl;\n    }\n    fclose(fp);\n}\n\nint main() {\n    write();\n    read();\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

看起来我的系统得到了提升,但好像 API 或其他东西发生了变化。这是什么问题,这是我的 Eclipse 输出:

\n\n
make all \nBuilding file: ../src/boostPopenHandler.cpp\nInvoking: GCC C++ Compiler\ng++ -D__GXX_EXPERIMENTAL_CXX0X__ -I../../emdw/src -I../../patrecII/src -I../../ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -MMD -MP -MF"src/boostPopenHandler.d" -MT"src/boostPopenHandler.d" -o"src/boostPopenHandler.o" "../src/boostPopenHandler.cpp"\nIn file included from ../src/boostPopenHandler.cpp:4:0:\n/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of \xe2\x80\x98boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = char; std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99:\n/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   required from \xe2\x80\x98boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = char; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]\xe2\x80\x99\n../src/boostPopenHandler.cpp:13:83:   required from here\n/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: error: invalid conversion from \xe2\x80\x98char\xe2\x80\x99 to \xe2\x80\x98const char*\xe2\x80\x99 [-fpermissive]\n     { open(detail::path(path), mode); }\n                                    ^\nIn file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,\n                 from ../src/boostPopenHandler.cpp:4:\n/usr/include/boost/iostreams/detail/path.hpp:52:5: error:   initializing argument 1 of \xe2\x80\x98boost::iostreams::detail::path::path(const char*)\xe2\x80\x99 [-fpermissive]\n     path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }\n     ^\nIn file included from ../src/boostPopenHandler.cpp:4:0:\n/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of \xe2\x80\x98boost::iostreams::file_descriptor_source::file_descriptor_source(const Path&, std::ios_base::openmode) [with Path = char; std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99:\n/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   required from \xe2\x80\x98boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = char; T = boost::iostreams::file_descriptor_source; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::input_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]\xe2\x80\x99\n../src/boostPopenHandler.cpp:26:85:   required from here\n/usr/include/boost/iostreams/device/file_descriptor.hpp:194:36: error: invalid conversion from \xe2\x80\x98char\xe2\x80\x99 to \xe2\x80\x98const char*\xe2\x80\x99 [-fpermissive]\n     { open(detail::path(path), mode); }\n                                    ^\nIn file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,\n                 from ../src/boostPopenHandler.cpp:4:\n/usr/include/boost/iostreams/detail/path.hpp:52:5: error:   initializing argument 1 of \xe2\x80\x98boost::iostreams::detail::path::path(const char*)\xe2\x80\x99 [-fpermissive]\n     path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }\n     ^\nmake: *** [src/boostPopenHandler.o] Error 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑
根据 Sel\xc3\xa7uk Cihan 的回答,我将相关代码更改为:

\n\n
boost::iostreams::file_descriptor_source fds(fd);\nboost::iostreams::stream_buffer<boost::iostreams::file_descriptor_sink> \n...\nboost::iostreams::file_descriptor_source fds(fd);\nboost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> \n
Run Code Online (Sandbox Code Playgroud)\n\n

但我仍然得到编译错误列表:

\n\n
**** Build of configuration Debug for project boostPopenHandler ****\n\nmake all \nBuilding file: ../src/boostPopenHandler.cpp\nInvoking: GCC C++ Compiler\ng++ -I../../emdw/src -I../../patrecII/src -I../../ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -MMD -MP -MF"src/boostPopenHandler.d" -MT"src/boostPopenHandler.d" -o"src/boostPopenHandler.o" "../src/boostPopenHandler.cpp"\nIn file included from ../src/boostPopenHandler.cpp:4:0:\n/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of \xe2\x80\x98boost::iostreams::file_descriptor_source::file_descriptor_source(const Path&, std::ios_base::openmode) [with Path = int; std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99:\n../src/boostPopenHandler.cpp:13:52:   required from here\n/usr/include/boost/iostreams/device/file_descriptor.hpp:194:36: error: invalid conversion from \xe2\x80\x98int\xe2\x80\x99 to \xe2\x80\x98const char*\xe2\x80\x99 [-fpermissive]\n     { open(detail::path(path), mode); }\n                                    ^\nIn file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,\n                 from ../src/boostPopenHandler.cpp:4:\n/usr/include/boost/iostreams/detail/path.hpp:52:5: error:   initializing argument 1 of \xe2\x80\x98boost::iostreams::detail::path::path(const char*)\xe2\x80\x99 [-fpermissive]\n     path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }\n     ^\nIn file included from ../src/boostPopenHandler.cpp:4:0:\n/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of \xe2\x80\x98boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99:\n/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   required from \xe2\x80\x98boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]\xe2\x80\x99\n../src/boostPopenHandler.cpp:14:84:   required from here\n/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: error: no matching function for call to \xe2\x80\x98boost::iostreams::detail::path::path(const boost::iostreams::file_descriptor_source&)\xe2\x80\x99\n     { open(detail::path(path), mode); }\n                                    ^\n/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36: note: candidates are:\nIn file included from /usr/include/boost/iostreams/device/file_descriptor.hpp:26:0,\n                 from ../src/boostPopenHandler.cpp:4:\n/usr/include/boost/iostreams/detail/path.hpp:138:5: note: boost::iostreams::detail::path::path(const wstring&)\n     path(const std::wstring&);\n     ^\n/usr/include/boost/iostreams/detail/path.hpp:138:5: note:   no known conversion for argument 1 from \xe2\x80\x98const boost::iostreams::file_descriptor_source\xe2\x80\x99 to \xe2\x80\x98const wstring& {aka const std::basic_string<wchar_t>&}\xe2\x80\x99\n/usr/include/boost/iostreams/detail/path.hpp:70:5: note: boost::iostreams::detail::path::path(const boost::iostreams::detail::path&)\n     path(const path& p) \n     ^\n/usr/include/boost/iostreams/detail/path.hpp:70:5: note:   no known conversion for argument 1 from \xe2\x80\x98const boost::iostreams::file_descriptor_source\xe2\x80\x99 to \xe2\x80\x98const boost::iostreams::detail::path&\xe2\x80\x99\n/usr/include/boost/iostreams/detail/path.hpp:64:14: note: template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::codecvt_type*)\n     explicit path(const Path& p, typename Path::codecvt_type* = 0)\n              ^\n/usr/include/boost/iostreams/detail/path.hpp:64:14: note:   template argument deduction/substitution failed:\n/usr/include/boost/iostreams/detail/path.hpp: In substitution of \xe2\x80\x98template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::codecvt_type*) [with Path = boost::iostreams::file_descriptor_source]\xe2\x80\x99:\n/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36:   required from \xe2\x80\x98boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99\n/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   required from \xe2\x80\x98boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]\xe2\x80\x99\n../src/boostPopenHandler.cpp:14:84:   required from here\n/usr/include/boost/iostreams/detail/path.hpp:64:14: error: no type named \xe2\x80\x98codecvt_type\xe2\x80\x99 in \xe2\x80\x98class boost::iostreams::file_descriptor_source\xe2\x80\x99\n/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of \xe2\x80\x98boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99:\n/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   required from \xe2\x80\x98boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]\xe2\x80\x99\n../src/boostPopenHandler.cpp:14:84:   required from here\n/usr/include/boost/iostreams/detail/path.hpp:57:14: note: template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::external_string_type*)\n     explicit path(const Path& p, typename Path::external_string_type* = 0)\n              ^\n/usr/include/boost/iostreams/detail/path.hpp:57:14: note:   template argument deduction/substitution failed:\n/usr/include/boost/iostreams/detail/path.hpp: In substitution of \xe2\x80\x98template<class Path> boost::iostreams::detail::path::path(const Path&, typename Path::external_string_type*) [with Path = boost::iostreams::file_descriptor_source]\xe2\x80\x99:\n/usr/include/boost/iostreams/device/file_descriptor.hpp:276:36:   required from \xe2\x80\x98boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99\n/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   required from \xe2\x80\x98boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]\xe2\x80\x99\n../src/boostPopenHandler.cpp:14:84:   required from here\n/usr/include/boost/iostreams/detail/path.hpp:57:14: error: no type named \xe2\x80\x98external_string_type\xe2\x80\x99 in \xe2\x80\x98class boost::iostreams::file_descriptor_source\xe2\x80\x99\n/usr/include/boost/iostreams/device/file_descriptor.hpp: In instantiation of \xe2\x80\x98boost::iostreams::file_descriptor_sink::file_descriptor_sink(const Path&, std::ios_base::openmode) [with Path = boost::iostreams::file_descriptor_source; std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99:\n/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   required from \xe2\x80\x98boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(U100&, typename boost::disable_if<boost::is_same<U0, T> >::type*) [with U100 = boost::iostreams::file_descriptor_source; T = boost::iostreams::file_descriptor_sink; Tr = std::char_traits<char>; Alloc = std::allocator<char>; Mode = boost::iostreams::output_seekable; typename boost::disable_if<boost::is_same<U0, T> >::type = void]\xe2\x80\x99\n../src/boostPopenHandler.cpp:14:84:   required from here\n/usr/include/boost/iostreams/detail/path.hpp:52:5: note: boost::iostreams::detail::path::path(const char*)\n     path(const char* p) : narrow_(p), wide_(), is_wide_(false) { }\n     ^\n/usr/include/boost/iostreams/detail/path.hpp:52:5: note:   no known conversion for argument 1 from \xe2\x80\x98const boost::iostreams::file_descriptor_source\xe2\x80\x99 to \xe2\x80\x98const char*\xe2\x80\x99\n/usr/include/boost/iostreams/detail/path.hpp:49:5: note: boost::iostreams::detail::path::path(const string&)\n     path(const std::string& p) : narrow_(p), wide_(), is_wide_(false) { }\n     ^\n/usr/include/boost/iostreams/detail/path.hpp:49:5: note:   no known conversion for argument 1 from \xe2\x80\x98const boost::iostreams::file_descriptor_source\xe2\x80\x99 to \xe2\x80\x98const string& {aka const std::basic_string<char>&}\xe2\x80\x99\n/usr/include/boost/iostreams/detail/path.hpp:46:5: note: boost::iostreams::detail::path::path()\n     path() : narrow_(), wide_(), is_wide_(false) { }\n     ^\n/usr/include/boost/iostreams/detail/path.hpp:46:5: note:   candidate expects 0 arguments, 1 provided\nmake: *** [src/boostPopenHandler.o] Error 1\n
Run Code Online (Sandbox Code Playgroud)\n

Sel*_*han 5

哦,你应该首先声明一个 file_descriptor_source 如

\n\n
boost::iostreams::file_descriptor_source fds(fd);\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后是你的流缓冲区

\n\n
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> bis(fds);\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑:

\n\n

抱歉造成混淆,带有 int 参数的 ctor 已被弃用,并且您似乎没有该 ctor,因为否则您的代码将完美编译。这就是为什么我提供的上述代码需要第二个强制参数boost::iostreams::never_close_handleboost::iostreams::close_handle

\n\n

所以它应该读

\n\n
boost::iostreams::file_descriptor_source fds(fd, boost::iostreams::close_handle);\n
Run Code Online (Sandbox Code Playgroud)\n\n

否则你仍然会得到这个错误。file_descriptor_sink 也有同样的修复。

\n\n

现在谈谈如何阅读错误:

\n\n
\n

/usr/include/boost/iostreams/device/file_descriptor.hpp: 在 \n \n \xe2\x80\x98boost::iostreams::file_descriptor_source::file_descriptor_source(const\n Path&, std::ios_base::openmode) 的实例化中) [路径 = char;\n std::ios_base::openmode = std::_Ios_Openmode]\xe2\x80\x99:

\n
\n\n

说它试图实例化一个 file_descriptor_source ,模板参数选择为

\n\n
\n

[路径=字符;std::ios_base::openmode = std::_Ios_Openmode]

\n
\n\n

由于您只提供了一个整数,编译器尝试匹配该版本的构造函数,但无法进行转换。

\n