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

Writing char* into a basic_streambuf and assign it to a ifstream

我有一个问题,主要是因为我无法真正理解如何处理这种情况。

我有一个 char* 大小为 X 的缓冲区,它是一个加密文件的内容,该文件已解密,然后将由 ifstream 处理程序 class 解析我无法编辑

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

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

但是当然,它不起作用,缓冲区没有写入 fstream 对象,您知道如何做到这一点吗?

我尝试了不同的方法,但我显然不知道该怎么做。

I'm trying to create a buffer type that can be parsed similarly to a 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用于将文本转换为二进制数据,e。 G。 int n; iss >> n;会将字符串“20102012”,由ascii序列0x32, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x32表示为对应的四字节整数值0x0132bb7c)。但是如果数据已经是二进制的,std::istringstream就不合适了。那么您可能宁愿尝试编写自己的流 class 类似于此示例:

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;
    }
};

您甚至可以将此 class 用于复杂的数据类型 - 但是请确保您适当地控制这些数据的字节对齐,否则您可能会严重失败!

看看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 Whosebug";
    io::stream< io::array_source > strm( buffer, sizeof(buffer) - 1 );  //-1 to strip '[=10=]'

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

Live Demo on Coliru.