今天實戰用boost庫中的方法,讀取xml格式文件。
博文中涉及到xml的解析,xml內容的提取,數據庫的創建,已經向數據庫中添加表,並向表中寫內容。
xml文件所在的目錄:
xml的文件內容:
具體代碼實現:
#include<iostream>
//起名
namespace bfs = boost::filesystem;
//創建一個db,我們使用sqlite這種小型數據庫,指針使用unique指針。
std::unique_ptr<SQLite::Database> createDb(const bfs::Path& dbPath)
{
if(bfs::exists(dbPath)) //判斷是否存在重名的db,如果有,刪除後再創建。
bfs::remove(dbPath);
//根據path創建一個unique指向的SQLite類型的數據庫
auto db = std::unique_shared<SQLite::Datebase>(dbPath.string(), SQLite::OPEN_READWRITE);
return db;
}
//提取數據。這裏第二參數是一個std::funtion,後面得總結下這玩意的用法。
int extractDataFromXml(const std::string& fileName, std::function<void(std::string &id, std::string data)> function)
{
//要讀取一個文件的內容,這兒得使用stream流來讀取。
std::ifstream file(fileName.c_str());
//然後從流中獲取數據!boost庫爲我們提供了從xml文件中讀取文件的方法。已經存儲的對象。
boost::property_tree::ptree tree;
boost::property_tree::xml_parser::read_xml(file, tree);
//我們獲取xml文件中的objects關鍵字
auto objects = tree.get_child("objects");
//objects裏面有無數個子項,現在循環遍歷
for(auto& object : objects)
{
const auto name = it->first;
auto& data = it->second; //當我們獲取容器或者其他存儲空間的內容時,我們不知道里面的大小的時候,應該以引用的興趣是獲取。
if (name == "ggg") //找到ggg的這一集配置
{
auto itemId = data.get_child("itemId").get_value<std::string>();
auto base64Data = data.get_child("data").get_value<std::string>();
auto resData = Base64Decode2(base64Data);
try
{
//我們這裏直接調用我們外面聲明的lambda函數。
func(std::move(itemId), std::move(resData)); //std的move方法使用,cppreferece查看一下。好像是不拷貝直接移除。
}
catch(...)
{
std::cout<<"hhh"<<std::endl;
}
}
}
}
void xml2Dbfile(const boost::filesystem::path& xmlsDir, const boost::filesystem::Path& fileDbPath)
//path所在的命名空間名太長了,我們t給起個短點的名字
{
//首先,第一步肯定得先創建一個db,應爲我們這個path的最後一級db目前還不存在
auto db = createDb(fileDbPath);
//因爲目錄中有不止一個xml文件,所以我們需要循環讀取。
//需要知道:directory_iterator() BOOST_NOEXCEPT {} // creates the "end" iterator
for(bfs::directory_iterator iter(xmlsDir); iter != bfs::directory_iterator(); ++iter)
{
//首先該文件一定要是有規律的文件的
if(bfs::is_regular_file(iter->path()))
{
//其次,該文件要是xml格式的文件
if(iter->path().extension() == ".xml")
{
//接下來,提取xml文件中的內容,提取之後寫到db中,寫成一張表
const auto infos = extractDataFromXml(iter->path().string(), [&](const std::string& dataId, const std::string& dataValue)
{
//在db中插入一張表,表名叫個fileData吧就
SQLite::Statement writer(*db, "insert into fileData(handle, data) values(:dataId, :dataValue)");
writer.bind(":dataId", dataID);
writer.bind(":dataValue", dataValue);
//執行語句
writer.exec();
});
}
}
}
}
int main()
{
const auto xmlsDir = "G:\\xmls"; //首先我們定義需要轉化的xml文件所在的目錄
const auto fileDbPath = "G:\\dbs\\fileDB"; //然後定義xml文件生成的db的path
try
{
xml2Dbfile(xmlsDir, fileDbPath);
}
}