2011-09-08 2 views
1

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

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.


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

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

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

ответ

3

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

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

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

0

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

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

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

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

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

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

+0

Нет, я знаю ссылки и указатели. _Streams_ кажутся лучше по сравнению с чистыми буферами данных, потому что вам не нужно передавать их размер вместе с ними (они более безопасны). Я хотел бы знать, как создать такой поток данных, но я не нашел никаких ресурсов в Интернете. –

+1

Вы передаете их размер вдоль них - он просто скрыт внутри объекта alon с реальными данными/содержимым. Вы можете сделать то же самое в C, передавая структуру с указателем, а также длиной. Чтобы создать собственный поток, используйте один из предопределенных классов потоков или создайте свой собственный производный класс, реализующий собственные версии различных методов-членов. – Mario

1

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

3

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

В частности, в Windows может использоваться дескриптор объекта HGLOBAL или раздела.

Философия C++ явно допускает множество разных стилей, в зависимости от контекста и среды. Привыкай к этому.

1

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

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

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

More on string streams here.

Смежные вопросы