Передача необработанных данных в C ++ - PullRequest
1 голос
/ 08 сентября 2011

До сих пор, когда бы я ни хотел передать некоторые необработанные данные в функцию (например, функцию, которая загружает изображение из буфера), я делал что-то вроде этого:

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

Сегодня я взялвзгляните на библиотеки Boost, точнее на заголовок property_tree/xml_parser.hpp, и я заметил подпись этой функции:

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

Это на самом деле заставило меня задуматься: это правильный способпередать необработанные данные в C ++, используя потоки?Или я неправильно понимаю, для чего должна использоваться функция?

Если это первое, не могли бы вы указать мне какой-нибудь ресурс, где я могу узнать, как использовать потоки для этого?Я сам почти ничего не нашел (в основном ссылки на API) и не смог найти исходный код Boost для синтаксического анализатора XML.


Редактировать: Некоторые дополнительные детали

Похоже, что я чего-то не понимаю.Учитывая данные буфера, как я могу преобразовать его в поток так, чтобы он был совместим с функцией read_xml, которую я опубликовал выше?Вот мой конкретный пример использования:

Я использую библиотеку SevenZip C для чтения XML-файла из архива.Библиотека предоставит мне буфер и его размер, и я хочу поместить его в потоковый формат, чтобы он был совместим с read_xml.Как я могу это сделать?

Ответы [ 5 ]

3 голосов
/ 08 сентября 2011

Не существует единственно правильного способа обхода буферов данных.Сочетание указателя и длины является наиболее простым способом;это C-friendly.Передача потока может позволить последовательную / частичную обработку, то есть не хранить весь файл в памяти одновременно.Если вы хотите передать изменяемый буфер (который может потенциально расти), vector<char>& будет хорошим выбором.

В частности, в Windows может использоваться HGLOBAL или дескриптор объекта секции.1005 * Философия C ++ явно допускает множество различных стилей, в зависимости от контекста и среды.Привыкай к этому.

3 голосов
/ 08 сентября 2011

Ну, потоки вполне используются в C ++ из-за их удобства:
- обработка ошибок
- они абстрагируют источник данных, поэтому независимо от того, читаете ли вы файл, аудиоисточник, камеру, все они рассматриваются как входные потоки
- и, вероятно, больше преимуществ, которые я не знаю,

Вот краткий обзор библиотеки IOstream, возможно, это может помочь вам лучше понять, что происходит с потоками: http://www.cplusplus.com/reference/iostream/

Понимание того, что они из себя представляют, поможет вам понять, как и когда их использовать.

1 голос
/ 08 сентября 2011

Кажется, было некое понимание того, чего я хочу. Учитывая данные буфера, как я могу преобразовать его в поток так, чтобы он был совместим с функцией read_xml, которую я опубликовал выше?

Легко (надеюсь PTree::Key_type::value_type будет что-то вроде char):

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

Подробнее о строковых потоках здесь .

1 голос
/ 08 сентября 2011

Буферы необработанной памяти в C ++ могут иметь тип unsigned char*, или вы можете создать std::vector<unsigned char>.Обычно вы не хотите использовать только char* для своего буфера, поскольку стандарт не гарантирует, что char будет использовать все биты в одном байте (т. Е. Это будет зависеть от платформы / компилятора).При этом потоки также отлично используются, учитывая, что вы можете использовать поток для чтения байтов из файла или другого ввода и т. Д., А оттуда хранить эти данные в буфере.

0 голосов
/ 08 сентября 2011

Это, по сути, использование ссылки для передачи содержимого потока. Так что за кулисами это, по сути, довольно похоже на то, что вы делали до сих пор, и это по сути то же самое - просто с использованием другой записи. Упрощенно, ссылка просто скрывает аспект указателя, поэтому в вашем примере надстройки вы по существу работаете с указателем на поток.

Ссылки получили преимущество, исключив все ссылки / разыменования, и поэтому их легче обрабатывать в большинстве ситуаций. Однако они не позволяют использовать несколько уровней (де) ссылок.

Следующие две примерные функции по сути одинаковы:

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

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

Говоря о самих передаваемых данных: это действительно зависит от того, чего вы пытаетесь достичь и что более эффективно. Если вы хотите изменить строку, использование объекта класса std::string может быть более удобным, чем использование классического указателя на буфер (char *). Преимущество потоков заключается в том, что они могут представлять несколько разных вещей (например, поток данных в сети, сжатый поток или просто поток файла или памяти). Таким образом, вы можете написать отдельные функции или методы, которые принимают поток в качестве входных данных и мгновенно будут работать, не беспокоясь о реальном источнике потока. Делать это с классическими буферами может быть сложнее. С другой стороны, вы не должны забывать, что все объекты будут добавлять некоторые накладные расходы, поэтому в зависимости от выполняемой работы простой указатель на строку символов может быть вполне подходящим (и наиболее эффективным решением). Нет «единственного способа сделать это».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...