将char *写入basic_streambuf并将其分配给ifstream

时间:2017-04-22 13:47:29

标签: c++ c++11 visual-c++ io streambuf

我遇到了问题,主要是因为我无法理解如何处理这种情况。

我有一个char*大小为X的缓冲区,它是一个加密文件的内容,它已被解密,然后由ifstream处理程序类解析,我可以不要编辑

所以我的想法是创建一个fstream对象,其中rdbuf()使用sputn分配缓冲区。

fstream _handle2; _handle2.rdbuf()->sputn(_buffer, _size); _handle2.flush();

但是,当然,它不起作用,缓冲区没有写入fstream对象,你知道如何制作它吗?

我尝试了不同的方法但我显然无法弄清楚要做什么。

2 个答案:

答案 0 :(得分:0)

  

我正在尝试创建一个可以与ifstream类似地解析的缓冲区类型。

你可以尝试这样的事情(从我在评论中提供的link中采用):

std::ifstream ifs("test.txt", std::ifstream::binary);
if (ifs)
{
    ifs.seekg (0, ifs.end);
    int length = ifs.tellg();
    ifs.seekg (0, ifs.beg);

    std::string buffer;
    buffer.resize(length);
    ifs.read(const_cast<char*>(buffer.data()), length);
    if (ifs)
    {
        // de-crypt the buffer here!
        // something like:
        // buffer[i] = decryptChar(buffer[i]);

        std::istringstream iss(buffer);

        // now you can use iss just the same way as ifs,
        // if the file was not encrypted...

    }
    else
    {
        std::cout << "error: only " << ifs.gcount() << " bytes could be read";
    }
    ifs.close();
}

根据您的评论进行修改:

std::istringstream用于将文本转换为二进制数据,例如: G。 int n; iss >> n;将字符串“20102012”转换为相应的四字节整数值0x0132bb7c,由ascii序列0x32,0x30,0x31,0x30,0x32,0x30,0x31,0x32表示。但是如果数据 已经是二进制的,那么std::istringstream就不合适了。然后你可能宁愿尝试编写自己的流类,类似于这个例子:

class DecryptionStream
{
    std::unique_ptr<char> mBuffer;
    char* mEnd;
    char* mPos;
    unsigned int flags;

    unsigned int const eofbit  = 1 << 0;
    unsigned int const failbit = 1 << 1;
    // other flag bits as needed

public:
    // fail/eof bits as needed
    DecryptionStream(char const* fileName) : mPos(nullptr)
    {
        std::ifstream ifs(fileName, std::ifstream::binary);
        if (ifs)
        {
            ifs.seekg (0, ifs.end);
            int length = ifs.tellg();
            ifs.seekg (0, ifs.beg);

            mBuffer.reset(new char[length]);
            ifs.read(mBuffer.get(), length);
            if (ifs)
            {
                // de-crypt the buffer here!
                // something like:
                // buffer[i] = decryptChar(buffer[i]);
                mPos = mBuffer.get();
                mEnd = mBuffer.get() + length;
            }
            else
            {
                flags |= failbit;
            }
            ifs.close();
        }
    }

    template<typename T>
    DecryptionStream& operator >>(T& t)
    {
        // fail, if any fail bit set already
        size_t avail = mPos - mEnd;
        if (avail < sizeof(t))
        {
            flags |= eofbit | failbit;
        }
        else
        {
            if(avail == sizeof(t))
            {
                flags |= eofbit;
            }
            memcpy(&t, mPos, sizeof(t));
            mPos += sizeof(t);
        }
        return *this;
    }

    operator bool()
    {
        return flags == 0;
    }
};

你甚至可以将这个类用于复杂的数据类型 - 然后确保你能够适当地控制这些数据的字节对齐,否则你可能会失败!

答案 1 :(得分:0)

查看boost::iostreams::array_source

它允许您将数组视为std::istream。优于std::istringstream的优点是阵列不会被复制到流中,从而减少了内存使用并提高了性能。 array_source将只存储指向现有缓冲区的指针。

#include <iostream>
#include <string>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
namespace io = boost::iostreams;

int main()
{   
    // Create an array and wrap a stream interface around it.
    const char buffer[] = "hello stackoverflow";
    io::stream< io::array_source > strm( buffer, sizeof(buffer) - 1 );  //-1 to strip '\0'

    // Use the stream like a standard istream.
    std::string s;
    while( strm >> s )
        std::cout << s << "\n";
}

Live Demo on Coliru.