Библиотека Boost, использующая std::wstring в качестве имени файла с boost::property_tree::read_xml

Недавно я начал использовать std::wstring вместо std::string, чтобы избежать странных результатов с символами, отличными от ASCII, и я не нашел способа прочитать файл XML, где путь имеет тип std::wstring, с помощью библиотеки boost.

Сейчас я часто использую библиотеку boost.

Я использую функцию boost::property_tree::read_xml с boost::property_tree::wptree вместо обычной структуры ptree. Но, к сожалению, я не могу передать std::wstring в качестве первого параметра для read_xml, что все усложняет.

Мой вопрос: есть ли обходной путь для чтения файла XML, где путь сохранен как std::wstring?

Заранее спасибо!


person Linus    schedule 29.08.2014    source источник


Ответы (2)


Вы можете использовать устройство Boost Iostreams file_descriptor_sink, которое поддерживает wpath файловой системы Boost:

#include <boost/property_tree/xml_parser.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/filesystem.hpp>
#include <iostream>

namespace pt = boost::property_tree;
namespace io = boost::iostreams;
namespace fs = boost::filesystem;

int main()
{
    fs::wpath const fname = L"test.xml";
    io::file_descriptor_source fs(fname);
    io::stream<io::file_descriptor_source> fsstream(fs);

    pt::ptree xml;
    pt::read_xml(fsstream, xml);

    for (auto const& node : xml.get_child("root"))
        std::cout << node.first << ": " << node.second.get_value<std::string>() << "\n";
}

Посмотрите Live On Coliru, где он использует входной файл:

<root>
    <child nodetype="element" with="attributes">monkey show</child>
    <child nodetype="element">monkey do</child>
</root>

и печатает:

child: monkey show
child: monkey do
person sehe    schedule 29.08.2014
comment
Это работает, если мое имя файла или путь содержат символы, отличные от ascii? - person ashish g; 29.01.2015
comment
@ashishg Я не проверял это, но я думаю, что boost::filesystem::path::codecvt() выполняет соответствующее преобразование, поэтому: да - person sehe; 29.01.2015
comment
coliru.stacked-crooked.com/a/7007dd21b1c12f14 Я попытался изменить ваш пример, чтобы включить не ascii и ошибка. - person ashish g; 29.01.2015
comment
@ashishg работает на меня. Как бы то ни было, добавление определенной локали *работает на Coliru - person sehe; 29.01.2015

Я нашел рабочее решение, которое было довольно простым, все, что я сделал, это использовал std::wifstream в качестве первого параметра метода boost::property_tree::read_xml.

В основном три строки кода:

boost::property_tree::wptree pt;
std::wifstream f(L"C:/äöå/file.xml");
boost::property_tree::read_xml(f, pt);
person Linus    schedule 29.08.2014
comment
Это не переносимо: en.cppreference.com/w/cpp/io/basic_ifstream/ basic_ifstream — по этой же причине boost::iostreams::file_source не поддерживает имена файлов с широкими строками (потому что они основаны на std::fstream) — именно по этой причине эта проблема #3088 помечена как WontFix. - person sehe; 30.08.2014
comment
@sehe Хорошо, но это работает в Microsoft Windows? Потому что мое приложение (пока) не кроссплатформенное. В любом случае спасибо за информацию и ответ. - person Linus; 30.08.2014
comment
Ваше здоровье. Я предполагаю, что это просто работает с реализацией стандартной библиотеки MSVC. (Он по-прежнему не будет работать с компиляторами MingW, GCC, Clang или Intel C++ в Windows). Это не первое, что есть нестандартного в MSVC. В общем, wstring редко используется за пределами Windows, потому что только в MSVC wstring имеет 16-битные типы char, и это совпадает с предпочтительной для Windows кодировкой символов UTF16. - person sehe; 30.08.2014
comment
@sehe Понятно, будет ли полезно использовать ваш метод при разработке в Windows и в Visual Studio? Vcredist будет установлен на всех компьютерах, на которых запущена моя программа. - person Linus; 30.08.2014
comment
Бьюсь об заклад, нет. Вы можете использовать расширение MSVC, если это все, что вы хотите поддерживать. (документы) - person sehe; 30.08.2014
comment
@sehe Хорошо, но пример был хорошим. Я не могу использовать wptree с помощью потока повышения, но в этом нет необходимости, если файл XML не содержит символы, отличные от ASCII? - person Linus; 30.08.2014