Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何构造c++;来自POSIX文件描述符的fstream? 我基本上是在寻找一个C++版本的fDOPENE()。我对此做了一些研究,这是其中一件看起来应该很容易的事情,但结果却非常复杂。我是否在这个信念中遗漏了什么(即,它真的很容易)?如果没有,有没有一个好的图书馆来处理这个问题 < >编辑:将我的示例解决方案移到单独的答案。 AFAIK,在标准C++中没有办法做到这一点。根据您的平台,标准库的实现可能提供(作为非标准扩展)一个fstream构造函数,该构造函数使用文件描述符(libstdc++,IIRC就是这种情况)或文件*作为输入 另一种选择是使用一个设备,如果你想有一个STD::流接口,可以在A中包起来。 < P>我的理解是,与C++指针流文件模型中的文件指针或文件描述符没有关联,以便保持代码可移植性。_C++_Posix_Fstream_File Descriptor - Fatal编程技术网

如何构造c++;来自POSIX文件描述符的fstream? 我基本上是在寻找一个C++版本的fDOPENE()。我对此做了一些研究,这是其中一件看起来应该很容易的事情,但结果却非常复杂。我是否在这个信念中遗漏了什么(即,它真的很容易)?如果没有,有没有一个好的图书馆来处理这个问题 < >编辑:将我的示例解决方案移到单独的答案。 AFAIK,在标准C++中没有办法做到这一点。根据您的平台,标准库的实现可能提供(作为非标准扩展)一个fstream构造函数,该构造函数使用文件描述符(libstdc++,IIRC就是这种情况)或文件*作为输入 另一种选择是使用一个设备,如果你想有一个STD::流接口,可以在A中包起来。 < P>我的理解是,与C++指针流文件模型中的文件指针或文件描述符没有关联,以便保持代码可移植性。

如何构造c++;来自POSIX文件描述符的fstream? 我基本上是在寻找一个C++版本的fDOPENE()。我对此做了一些研究,这是其中一件看起来应该很容易的事情,但结果却非常复杂。我是否在这个信念中遗漏了什么(即,它真的很容易)?如果没有,有没有一个好的图书馆来处理这个问题 < >编辑:将我的示例解决方案移到单独的答案。 AFAIK,在标准C++中没有办法做到这一点。根据您的平台,标准库的实现可能提供(作为非标准扩展)一个fstream构造函数,该构造函数使用文件描述符(libstdc++,IIRC就是这种情况)或文件*作为输入 另一种选择是使用一个设备,如果你想有一个STD::流接口,可以在A中包起来。 < P>我的理解是,与C++指针流文件模型中的文件指针或文件描述符没有关联,以便保持代码可移植性。,c++,posix,fstream,file-descriptor,C++,Posix,Fstream,File Descriptor,也就是说,我看到有几个地方提到了或boost来帮助弥补这一差距。您的编译器很有可能提供基于文件的fstream构造函数,尽管它是非标准的。例如: FILE* f = fdopen(my_fd, "a"); std::fstream fstr(f); fstr << "Greetings\n"; FILE*f=fdopen(my_fd,“a”); std::fstream fstr(f); fstr根据埃里克·马伦芬特给出的答案: 哎呀,这是不可能的 标准C++。取决于你的 平台,您

也就是说,我看到有几个地方提到了或boost来帮助弥补这一差距。

您的编译器很有可能提供基于文件的fstream构造函数,尽管它是非标准的。例如:

FILE* f = fdopen(my_fd, "a");
std::fstream fstr(f);
fstr << "Greetings\n";
FILE*f=fdopen(my_fd,“a”);
std::fstream fstr(f);

fstr根据埃里克·马伦芬特给出的答案:


哎呀,这是不可能的 标准C++。取决于你的 平台,您实现的 标准图书馆可提供(作为 非标准扩展)fstream 采用文件描述符的构造函数 作为输入。(这是我们的情况 libstdc++,IIRC)或文件*

基于以上观察和我在下面的研究,有两种变体的工作代码;一个为LIbSTDC++ +,另一个为微软Visual C++。
libstdc++ 有一个非标准类模板继承了
std::basic\u streambuf
,并具有以下构造函数

stdio_filebuf (int __fd, std::ios_base::openmode __mode, size_t __size=static_cast< size_t >(BUFSIZ)) 
而且它没有文档记录(我甚至找不到任何可能存在的旧文档)。我们调用它(第1行),参数是调用从POSIX文件句柄获取C流文件*的结果

#include <cstdio>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
    ofstream ofs("test.txt");
    ofs << "Writing to a basic_ofstream object..." << endl;
    ofs.close();

    int posix_handle = ::_fileno(::fopen("test.txt", "r"));

    ifstream ifs(::_fdopen(posix_handle, "r")); // 1

    string line;
    getline(ifs, line);
    ifs.close();
    cout << "line: " << line << endl;
    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
ofs流(“test.txt”);
ofs这个问题最初(未说明)的动机之一是能够使用安全创建的临时文件在程序之间或测试程序的两个部分之间传递数据,但是tmpnam()在gcc中抛出了一个警告,所以我想使用mkstemp()取而代之。这是我根据埃里克·马伦芬特给出的答案编写的测试程序,但使用mkstemp()而不是fdopen();这在安装了Boost库的Ubuntu系统上运行:

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>

using boost::iostreams::stream;
using boost::iostreams::file_descriptor_sink;
using boost::filesystem::path;
using boost::filesystem::exists;
using boost::filesystem::status;
using boost::filesystem::remove;

int main(int argc, const char *argv[]) {
  char tmpTemplate[13];
  strncpy(tmpTemplate, "/tmp/XXXXXX", 13);
  stream<file_descriptor_sink> tmp(mkstemp(tmpTemplate));
  assert(tmp.is_open());
  tmp << "Hello mkstemp!" << std::endl;
  tmp.close();
  path tmpPath(tmpTemplate);
  if (exists(status(tmpPath))) {
    std::cout << "Output is in " << tmpPath.file_string() << std::endl;
    std::string cmd("cat ");
    cmd += tmpPath.file_string();
    system(cmd.c_str());
    std::cout << "Removing " << tmpPath.file_string() << std::endl;
    remove(tmpPath);
  }
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用boost::iostreams::stream;
使用boost::iostreams::文件\描述符\接收器;
使用boost::filesystem::path;
使用boost::filesystem::exists;
使用boost::filesystem::status;
使用boost::filesystem::remove;
int main(int argc,const char*argv[]{
char-tmpTemplate[13];
strncpy(tmp模板,“/tmp/XXXXXX”,13);
流tmp(mkstemp(tmpTemplate));
断言(tmp.is_open());

tmp我尝试了上面Piotr Dobrogost为libstdc++提出的解决方案,发现它有一个令人痛苦的缺陷:由于缺乏一个适当的istream移动构造函数,很难将新构造的istream对象从创建函数中取出。另一个问题是它泄漏了一个FILE对象(甚至不考虑底层posix文件描述符)。这里有一个替代解决方案可以避免这些问题:

#include <fstream>
#include <string>
#include <ext/stdio_filebuf.h>
#include <type_traits>

bool OpenFileForSequentialInput(ifstream& ifs, const string& fname)
{
    ifs.open(fname.c_str(), ios::in);
    if (! ifs.is_open()) {
        return false;
    }

    using FilebufType = __gnu_cxx::stdio_filebuf<std::ifstream::char_type>;
    static_assert(  std::is_base_of<ifstream::__filebuf_type, FilebufType>::value &&
                    (sizeof(FilebufType) == sizeof(ifstream::__filebuf_type)),
            "The filebuf type appears to have extra data members, the cast might be unsafe");

    const int fd = static_cast<FilebufType*>(ifs.rdbuf())->fd();
    assert(fd >= 0);
    if (0 != posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
        ifs.close();
        return false;
    }

    return true;
}
#包括
#包括
#包括
#包括
bool OpenFileForSequentialInput(ifstream&ifs、const string&fname)
{
ifs.open(fname.c_str(),ios::in);
如果(!ifs.is_open()){
返回false;
}
使用FilebufType=\uuu gnu\ucxx::stdio\u filebuf;
静态断言(std::是::值的基础&&
(sizeof(FilebufType)==sizeof(ifstream::\u filebuf\u type)),
“filebuf类型似乎有额外的数据成员,强制转换可能不安全”);
const int fd=static_cast(ifs.rdbuf())->fd();
断言(fd>=0);
如果(0!=posix_fadvise(fd,0,0,posix_FADV_顺序)){
ifs.close();
返回false;
}
返回true;
}

对posix_fadvise()的调用演示了一个潜在的用途。注意,这个例子使用了StistaSyrt,使用C++ 11,而不是在C++ 03模式下构建得很好。

< P>它很简单。Nicolai M. Josuttis已经与他的书一起发布了<代码> FDSturi>代码。你可以找到184行实现。因此,我不明白C++ C++流如何使用C流可能会造成伤害。portability@Kazark-现在转移到单独的答案,谢谢。Windows和Linux可以对文件执行
mmap
,并将其内容作为字节数组公开。由于完整性,现在接受答案。其他人可能对使用boost的解决方案感兴趣,它具有对于linux:如果你看一下gcc中的ios_init.cc(我的源代码是4.1.1版)std::cout是通过在文件描述符周围初始化一个stdio_sync_文件buf,然后在stdio_sync_文件buf周围的ostream上初始化来初始化的。但我不能说这是稳定的。@Sparky研究
std::cout
实现是个好主意。我想知道
stdio_文件buf 和
stdio_sync_filebuf
?MSVC中的POSIX FD是仿真。用于文件操作的Windows API在许多方面不同于POSIX API-不同的函数名和参数的数据类型。Windows内部使用所谓的“句柄”要识别各种Windows API对象,Windows API类型句柄被定义为void*,因此它至少不适合64位平台上的“int”(32位)。因此,对于Windows,您可能会感兴趣
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>

using boost::iostreams::stream;
using boost::iostreams::file_descriptor_sink;
using boost::filesystem::path;
using boost::filesystem::exists;
using boost::filesystem::status;
using boost::filesystem::remove;

int main(int argc, const char *argv[]) {
  char tmpTemplate[13];
  strncpy(tmpTemplate, "/tmp/XXXXXX", 13);
  stream<file_descriptor_sink> tmp(mkstemp(tmpTemplate));
  assert(tmp.is_open());
  tmp << "Hello mkstemp!" << std::endl;
  tmp.close();
  path tmpPath(tmpTemplate);
  if (exists(status(tmpPath))) {
    std::cout << "Output is in " << tmpPath.file_string() << std::endl;
    std::string cmd("cat ");
    cmd += tmpPath.file_string();
    system(cmd.c_str());
    std::cout << "Removing " << tmpPath.file_string() << std::endl;
    remove(tmpPath);
  }
}
#include <fstream>
#include <string>
#include <ext/stdio_filebuf.h>
#include <type_traits>

bool OpenFileForSequentialInput(ifstream& ifs, const string& fname)
{
    ifs.open(fname.c_str(), ios::in);
    if (! ifs.is_open()) {
        return false;
    }

    using FilebufType = __gnu_cxx::stdio_filebuf<std::ifstream::char_type>;
    static_assert(  std::is_base_of<ifstream::__filebuf_type, FilebufType>::value &&
                    (sizeof(FilebufType) == sizeof(ifstream::__filebuf_type)),
            "The filebuf type appears to have extra data members, the cast might be unsafe");

    const int fd = static_cast<FilebufType*>(ifs.rdbuf())->fd();
    assert(fd >= 0);
    if (0 != posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
        ifs.close();
        return false;
    }

    return true;
}