如何在std :: iostream中使用QFile?

And*_*oth 9 qt iostream stl

是否可以使用像std :: iostream这样的QFile?我很确定那里必须有一个包装纸.问题是在哪里?

我有另一个libs,它需要一个std :: istream作为输入参数,但在我的程序中我此时只有一个QFile.

And*_*oth 7

我使用以下代码提出了自己的解决方案:

#include <ios>
#include <QIODevice>

class QStdStreamBuf : public std::streambuf
{
public:
    QStdStreamBuf(QIODevice *dev) : std::streambuf(), m_dev(dev)
    {
        // Initialize get pointer.  This should be zero so that underflow is called upon first read.
        this->setg(0, 0, 0);
    }

protected:
virtual std::streamsize xsgetn(std::streambuf::char_type *str, std::streamsize n)
{
    return m_dev->read(str, n);
}

virtual std::streamsize xsputn(const std::streambuf::char_type *str, std::streamsize n)
{
    return m_dev->write(str, n);
}

virtual std::streambuf::pos_type seekoff(std::streambuf::off_type off, std::ios_base::seekdir dir, std::ios_base::openmode /*__mode*/)
{
    switch(dir)
    {
        case std::ios_base::beg:
            break;
        case std::ios_base::end:
            off = m_dev->size() - off;
            break;
        case std::ios_base::cur:
            off = m_dev->pos() + off;
            break;
    }
    if(m_dev->seek(off))
        return m_dev->pos();
    else
        return std::streambuf::pos_type(std::streambuf::off_type(-1));
}
virtual std::streambuf::pos_type seekpos(std::streambuf::pos_type off, std::ios_base::openmode /*__mode*/)
{
    if(m_dev->seek(off))
        return m_dev->pos();
    else
        return std::streambuf::pos_type(std::streambuf::off_type(-1));
}

virtual std::streambuf::int_type underflow()
{ 
    // Read enough bytes to fill the buffer.
    std::streamsize len = sgetn(m_inbuf, sizeof(m_inbuf)/sizeof(m_inbuf[0]));

    // Since the input buffer content is now valid (or is new)
    // the get pointer should be initialized (or reset).
    setg(m_inbuf, m_inbuf, m_inbuf + len);

    // If nothing was read, then the end is here.
    if(len == 0)
        return traits_type::eof();

    // Return the first character.
    return traits_type::not_eof(m_inbuf[0]);
}


private:
    static const std::streamsize BUFFER_SIZE = 1024;
    std::streambuf::char_type m_inbuf[BUFFER_SIZE];
    QIODevice *m_dev;
};

class QStdIStream : public std::istream
{
public:
    QStdIStream(QIODevice *dev) : std::istream(m_buf = new QStdStreamBuf(dev)) {}
    virtual ~QStdIStream()
    {
        rdbuf(0);
        delete m_buf;
    }

private:
    QStdStreamBuf * m_buf;
};
Run Code Online (Sandbox Code Playgroud)

我工作正常,可以读取本地文件.我还没有测试它来写文件.这段代码肯定不完美,但它确实有效.


Pio*_*ost 5

我提出了自己的解决方案(使用了与Stephen Chu建议相同的想法)

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

#include <QtCore>

using namespace std;

void externalLibFunction(istream & input_stream) {
    copy(istream_iterator<string>(input_stream),
         istream_iterator<string>(),
         ostream_iterator<string>(cout, " "));
}

ifstream QFileToifstream(QFile & file) {
    Q_ASSERT(file.isReadable());        
    return ifstream(::_fdopen(file.handle(), "r"));
}

int main(int argc, char ** argv)
{
    QFile file("a file");
    file.open(QIODevice::WriteOnly);
    file.write(QString("some string").toLatin1());
    file.close();
    file.open(QIODevice::ReadOnly);
    std::ifstream ifs(QFileToifstream(file));
    externalLibFunction(ifs);
}
Run Code Online (Sandbox Code Playgroud)

输出:

some string
Run Code Online (Sandbox Code Playgroud)

此代码使用工作草案,编程语言C++标准的 27.9.1.7 basic_ifstream构造函数部分中指定的std :: ifstream移动构造函数(C++ x0特性):

basic_ifstream(basic_ifstream&& rhs);
效果:从rvalue rhs移动构造.这是通过移动构造基类和包含的basic_filebuf来实现的.调用next basic_istream :: set_rdbuf(&sb)来安装包含的basic_filebuf.

有关此主题的讨论,请参见如何返回fstream(C++ 0x).

  • 对于'ifstream(:: _ fdopen(file.handle(),“ r”));'行:错误:没有匹配函数调用'std :: basic_ifstream &lt;char&gt; :: basic_ifstream(FILE *) 'std :: ifstream fileInputStream(:: _ fdopen(testPatternPng.handle(),“ r”));` (3认同)