更简单的方法从(char *,size_t)创建一个C + + memorystream,而不复制数据? [英] Simpler way to create a C++ memorystream from (char*, size_t), without copying the data?

查看:565
本文介绍了更简单的方法从(char *,size_t)创建一个C + + memorystream,而不复制数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找不到任何现成的,所以我想出了:

  class membuf:public basic_streambuf< char> ; 
{
public:
membuf(char * p,size_t n){
setg(p,p,p + n);
setp(p,p + n);
}
}

用法:

  char * mybuffer; 
size_t length;
// ...分配mybuffer,将数据放入其中,设置length

membuf mb(mybuffer,length);
istream reader(& mb);
//使用reader

我知道 stringstream ,但它似乎不能处理给定长度的二进制数据。



我是在这里发明自己的车轮吗? p>

编辑




  • / strong>复制输入数据,只需创建一个可以迭代数据的东西。

  • 它必须是可移植的 - 至少它应该在gcc和MSVC下工作。


解决方案

我假设你的输入数据是二进制文本而不是文本的二进制数据。



您可以结合使用 boost :: iostreams :: basic_array_source code> boost :: iostreams :: stream_buffer (来自 Boost.Iostreams )与 boost :: archive :: binary_iarchive (从Boost.Serialization ),以便能够使用方便的提取>>运算符读取二进制数据块。

  #include< stdint.h> 
#include< iostream>
#include< boost / iostreams / device / array.hpp>
#include< boost / iostreams / stream.hpp>
#include< boost / archive / binary_iarchive.hpp>

int main()
{
uint16_t data [] = {1234,5678};
char * dataPtr =(char *)& data;

typedef boost :: iostreams :: basic_array_source< char>设备;
boost :: iostreams :: stream_buffer< Device> buffer(dataPtr,sizeof(data));
boost :: archive :: binary_iarchive archive(buffer,boost :: archive :: no_header);

uint16_t word1,word2;
archive>> word1>> word2;
std :: cout<< word1<< ,< word2<< std :: endl;
return 0;
}

在AMD64上使用GCC 4.4.1时,它输出:


1234,5678


Boost.Serialization非常强大,知道如何序列化所有基本类型,字符串,甚至STL容器。你可以很容易地使你的类型可序列化。请参阅文档。隐藏在Boost.Serialization源中的某个地方是一个便携式二进制归档的示例,它知道如何对您的机器的字节序执行正确的交换。



如果你不需要Boost.Serialization的乐观,并乐意读取fread()中的二进制数据 - 可以使用更简单的方法使用 basic_array_source

  include< stdint.h> 
#include< iostream>
#include< boost / iostreams / device / array.hpp>
#include< boost / iostreams / stream.hpp>

int main()
{
uint16_t data [] = {1234,5678};
char * dataPtr =(char *)& data;

typedef boost :: iostreams :: basic_array_source< char>设备;
boost :: iostreams :: stream< Device> stream(dataPtr,sizeof(data));

uint16_t word1,word2;
stream.read((char *)& word1,sizeof(word1));
stream.read((char *)& word2,sizeof(word2));
std :: cout<< word1<< ,< word2<< std :: endl;

return 0;
}

我得到与此程序相同的输出。


I couldn't find anything ready-made, so I came up with:

class membuf : public basic_streambuf<char>
{
public:
  membuf(char* p, size_t n) {
    setg(p, p, p + n);
    setp(p, p + n);
  }
}

Usage:

char *mybuffer;
size_t length;
// ... allocate "mybuffer", put data into it, set "length"

membuf mb(mybuffer, length);
istream reader(&mb);
// use "reader"

I know of stringstream, but it doesn't seem to be able to work with binary data of given length.

Am I inventing my own wheel here?

EDIT

  • It must not copy the input data, just create something that will iterate over the data.
  • It must be portable - at least it should work both under gcc and MSVC.

解决方案

I'm assuming that your input data is binary (not text), and that you want to extract chunks of binary data from it. All without making a copy of your input data.

You can combine boost::iostreams::basic_array_source and boost::iostreams::stream_buffer (from Boost.Iostreams) with boost::archive::binary_iarchive (from Boost.Serialization) to be able to use convenient extraction >> operators to read chunks of binary data.

#include <stdint.h>
#include <iostream>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/archive/binary_iarchive.hpp>

int main()
{
    uint16_t data[] = {1234, 5678};
    char* dataPtr = (char*)&data;

    typedef boost::iostreams::basic_array_source<char> Device;
    boost::iostreams::stream_buffer<Device> buffer(dataPtr, sizeof(data));
    boost::archive::binary_iarchive archive(buffer, boost::archive::no_header);

    uint16_t word1, word2;
    archive >> word1 >> word2;
    std::cout << word1 << "," << word2 << std::endl;
    return 0;
}

With GCC 4.4.1 on AMD64, it outputs:

1234,5678

Boost.Serialization is very powerful and knows how to serialize all basic types, strings, and even STL containers. You can easily make your types serializable. See the documentation. Hidden somewhere in the Boost.Serialization sources is an example of a portable binary archive that knows how to perform the proper swapping for your machine's endianness. This might be useful to you as well.

If you don't need the fanciness of Boost.Serialization and are happy to read the binary data in an fread()-type fashion, you can use basic_array_source in a simpler way:

#include <stdint.h>
#include <iostream>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

int main()
{
    uint16_t data[] = {1234, 5678};
    char* dataPtr = (char*)&data;

    typedef boost::iostreams::basic_array_source<char> Device;
    boost::iostreams::stream<Device> stream(dataPtr, sizeof(data));

    uint16_t word1, word2;
    stream.read((char*)&word1, sizeof(word1));
    stream.read((char*)&word2, sizeof(word2));
    std::cout << word1 << "," << word2 << std::endl;

    return 0;
}

I get the same output with this program.

这篇关于更简单的方法从(char *,size_t)创建一个C + + memorystream,而不复制数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆