简体   繁体   English

在 C++ 中传递原始数据

[英]Passing raw data in C++

Up until now, whenever I wanted to pass some raw data to a function (like a function that loads an image from a buffer), I would do something like this:到目前为止,每当我想将一些原始数据传递给函数(例如从缓冲区加载图像的函数)时,我都会执行以下操作:

void Image::load(const char* buffer, std::size_t size);

Today I took a look at the Boost libraries, more specifically at the property_tree/xml_parser.hpp header, and I noticed this function signature:今天我查看了 Boost 库,更具体地说是在property_tree/xml_parser.hpp头文件中,我注意到了这个函数签名:

 template<typename Ptree> 
 void read_xml(std::basic_istream<typename Ptree::key_type::value_type>&, 
               Ptree &, int = 0);

This actually made me curious: is this the correct way to pass around raw data in C++, by using streams?这实际上让我感到好奇:这是使用流在 C++ 中传递原始数据的正确方法吗? Or am I misinterpreting what the function is supposed to be used for?还是我误解了该函数的用途?

If it's the former, could you please point me to some resource where I can learn how to use streams for this?如果是前者,能否请您指点我一些可以学习如何使用流的资源? I haven't found much myself (mainly API references), and I have't been able to find the Boost source code for the XML parser either.我自己没有找到太多东西(主要是 API 参考),我也找不到 XML 解析器的 Boost 源代码。


Edit: Some extra details编辑:一些额外的细节

Seems there's been some confusion as to what I want.似乎对我想要什么有些困惑。 Given a data buffer, how can I convert it to a stream such that it is compatible with the read_xml function I posted above?给定一个数据缓冲区,如何将其转换为流,使其与我上面发布的read_xml函数兼容? Here's my specific use case:这是我的具体用例:

I'm using the SevenZip C library to read an XML file from an archive.我正在使用SevenZip C 库从存档中读取 XML 文件。 The library will provide me with a buffer and its size, and I want to put that in stream format such that it is compatible with read_xml .该库将为我提供一个缓冲区及其大小,我想将其置于流格式中,以便与read_xml兼容。 How can I do that?我怎样才能做到这一点?

Well, streams are quite used in C++ because of their conveniences:嗯,流在 C++ 中非常常用,因为它们很方便:
- error handling - 错误处理
- they abstract away the data source, so whether you are reading from a file, an audio source, a camera, they are all treated as input streams - 它们抽象出数据源,因此无论您是从文件、音频源还是相机中读取,它们都被视为输入流
- and probably more advantages I don't know of - 可能还有更多我不知道的优势

Here is an overview of the IOstream library, perhaps that might better help you understand what's going on with streams: http://www.cplusplus.com/reference/iostream/这是 IOstream 库的概述,也许可以更好地帮助您了解流的情况: http ://www.cplusplus.com/reference/iostream/

Understanding what they are exactly will help you understand how and when to use them.了解它们究竟是什么将帮助您了解如何以及何时使用它们。

There's no single correct way to pass around data buffers.没有单一的正确方法来传递数据缓冲区。 A combination of pointer and length is the most basic way;指针和长度的组合是最基本的方式; it's C-friendly.它是 C 友好的。 Passing a stream might allow for sequential/chunked processing - ie not storing the whole file in memory at the same time.传递流可能允许顺序/分块处理 - 即不在同一时间将整个文件存储在内存中。 If you want to pass a mutable buffer (that might potentially grow), a vector<char>& would be a good choice.如果您想传递可变缓冲区(可能会增长), vector<char>&将是一个不错的选择。

Specifically on Windows, a HGLOBAL or a section object handle might be used.特别是在 Windows 上,可能会使用 HGLOBAL 或节对象句柄。

The C++ philosophy explicitly allows for many different styles, depending on context and environment. C++ 哲学明确允许许多不同的风格,具体取决于上下文和环境。 Get used to it.习惯它。

Buffers of raw memory in C++ can either be of type unsigned char* , or you can create a std::vector<unsigned char> . C++ 中的原始内存缓冲区可以是unsigned char*类型,也可以创建一个std::vector<unsigned char> You typically don't want to use just a char* for your buffer since char is not guaranteed by the standard to use all the bits in a single byte (ie, this will end up varying by platform/compiler).您通常不想只对缓冲区使用char* ,因为标准不保证char使用单个字节中的所有位(即,这最终会因平台/编译器而异)。 That being said, streams have some excellent uses as well, considering that you can use a stream to read bytes from a file or some other input, etc., and from there, store that data in a buffer.话虽如此,流也有一些很好的用途,考虑到您可以使用流从文件或其他输入等读取字节,然后从那里将该数据存储在缓冲区中。

Seems there's been some confusion as to what I want.似乎对我想要什么有些困惑。 Given a data buffer, how can I convert it to a stream such that it is compatible with the read_xml function I posted above?给定一个数据缓冲区,如何将其转换为流,以便与我上面发布的 read_xml 函数兼容?

Easily (I hope PTree::Key_type::value_type would be something like char ):很容易(我希望PTree::Key_type::value_type类似于char ):

istringstream stream(string(data, len));
read_xml(stream, ...);

More on string streams here . 更多关于这里的字符串流

This is essentially using a reference to pass the stream contents.这实质上是使用引用来传递流内容。 So behind the scene's it's essentially rather similar to what you did so far and it's essentially the same - just using a different notation.所以在幕后,它本质上与你目前所做的非常相似,而且本质上是相同的——只是使用了不同的符号。 Simplified, the reference just hides the pointer aspect, so in your boost example you're essentially working with a pointer to the stream.简而言之,引用只是隐藏了指针方面,因此在您的 boost 示例中,您实际上是在使用指向流的指针。

References got the advantage avoiding all the referencing/dereferencing and are therefore easier to handle in most situations.引用具有避免所有引用/取消引用的优势,因此在大多数情况下更容易处理。 However they don't allow you multiple levels of (de-)referencing.但是,它们不允许您进行多级(取消)引用。

The following two example functions do essentially the same:以下两个示例函数的作用基本相同:

void change_a(int &var, myclass &cls)
{
    var = cls.convert();
}

void change_b(int *var, myclass *cls)
{
    *var = cls->convert();
}

Talking about the passed data itself: It really depends on what you're trying to achieve and what's more effective.谈论传递的数据本身:这实际上取决于您要实现的目标以及更有效的目标。 If you'd like to modify a string, utilizing an object of class std::string might be more convenient than using a classic pointer to a buffer ( char * ).如果您想修改字符串,使用std::string类的对象可能比使用指向缓冲区的经典指针 ( char * ) 更方便。 Streams got the advantage that they can represent several different things (eg data stream on the network, a compressed stream or simply a file or memory stream).流的优势在于它们可以表示几种不同的事物(例如网络上的数据流、压缩流或简单的文件或内存流)。 This way you can write single functions or methods that accept a stream as input and will instantly work without worrying about the actual stream source.通过这种方式,您可以编写接受流作为输入的单个函数或方法,并且可以立即工作而无需担心实际的流源。 Doing this with classic buffers can be more complicated.使用经典缓冲区执行此操作可能会更复杂。 On the other side you shouldn't forget that all objects will add some overhead, so depending on the job to be done a simple pointer to a character string might be perfectly fine (and the most effective solution).另一方面,您不应该忘记所有对象都会增加一些开销,因此根据要完成的工作,指向字符串的简单指针可能非常好(也是最有效的解决方案)。 There's no "the one way to do it".没有“唯一的方法”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM