将 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";
}
我有一个问题,主要是因为我无法真正理解如何处理这种情况。
我有一个 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";
}