Передача ifstream, созданного из встроенного файла ресурсов, в ускоренный анализатор XML

#c #boost #buffer #ifstream

#c #ускорять #буфер #ifstream

Вопрос:

Я пытаюсь проанализировать XML-файл встроенного ресурса:

 HRSRC hresinfo = FindResource(hInstance, MAKEINTRESOURCE(IDR_XML1), _T("XML"));
if (hresinfo)
{
    HGLOBAL hRes = LoadResource(hInstance, hresinfo);
    DWORD datasize = SizeofResource(hInstance, hresinfo); // this size is correct
    LPVOID data = LockResource(hRes);

    if (hRes amp;amp; datasize != 0 amp;amp; data) {
        ifstream in;
        in.rdbuf()->pubsetbuf((char*)data, datasize);

        streamsize size = in.rdbuf()->in_avail();
        printf("size=%d", size); // this size is 0
        
        pt::read_xml(in, tree); // parses nothing
    }
    else {
        printf("error: %dn", GetLastError());
    }
}
  

memcpy загружает данные в обычный буфер и печатает каждый символ, что наводит меня на мысль, что проблема связана с ifstream.

Комментарии:

1. В чем именно проблема?

2. В rdbuf ничего нет, даже несмотря на то, что в него были введены данные, и указатель данных и datasize указаны правильно. @ted-lyngmo

3. Если вы сначала попробуете средний шаг: std::string buf(datasize, ''); std::copy_n((char*)data, datasize, buf.data()); получаете ли вы данные в buf ?

4. Какую версию boost вы используете? void read_xml(const std::string amp;, Ptree amp;, int = 0, const std::locale amp; = std::locale()); кажется, это лучше, чем настройка rdbuf . Это означало бы: pt::read_xml((const char*)data, tree); должно работать напрямую.

5. Первый параметр void read_xml(const std::string amp;, Ptree amp;, int = 0, const std::locale amp; = std::locale()); указывает имя файла для открытия. Я не могу передать имя файла, поскольку файл является встроенным ресурсом. Другое определение для этой функции принимает входной поток.

Ответ №1:

Я думаю, что pubsetbuf не делает того, что вам нужно (однако я не совсем понимаю, что именно он делает). Чтобы установить std::ifstream содержимое в том виде, в каком оно было загружено из реального файла, вы можете сделать следующее:

     std::ifstream in;
    std::stringstream ss{std::string((char*)data, datasize)};
    in.basic_ios<char>::rdbuf(ss.rdbuf());
    std::string str;
    in >> str;  // to check if ifstream has expected content
    std::cout << "str = " << str << std::endl;
  

Ваш ifstream будет использовать тот же контент, который stringstream создан из необработанного блока памяти, указанного data .

Редактировать

Извините, забыл std::ifstream . Я вижу, что это pt::read_xml принимается std::basic_istream , поэтому просто передайте std::stringstream напрямую.

Комментарии:

1. По какой-то причине, хотя std::string ((char*)data, datasize); там содержится полное содержимое файла, буфер ifstream содержит только первые 5 символов. Размер буфера ifstream не достигает 5 байт datasize .

2. Хм, немного странно, что ifstream у вас тоже не сработало. У меня это работало с поддельными данными, даже если они содержали нулевой символ: char* buff = "abdcefghijk"; std::stringstream ss{std::string(buff, 13)}; in.basic_ios<char>::rdbuf(ss.rdbuf()); std::string str; in >> str; std::cout << "str = " << str << std::endl;