PHP学习笔记,通用配置文件读写类与格式转换

  xml已经被json逐步取代,今后用的api都是用貌似用的json,不过有个别老的网站依旧在用xml。

property_tree是贰个保存了多少个属性值的树形数据结构,能够用来解析xml、json、ini、info文件。要采取property_tree和xml解析组件的话要求包蕴”boost/property_tree/ptree.hpp”和”boost/property_tree/xml_parser.hpp”。大家一般采取property_tree中约定义好的typedef:
ptree来拍卖多少。

  xml已经被json慢慢替代,将来用的api都是用貌似用的json,但是有个别老的网站依然在用xml。

.NET下编写程序的时候时不时会使用到布局文件。配置文件格式日常有xmlinijson等三种,操作分歧品类配置文件要求利用分裂的法子,操作相比麻烦。特别是指向同时接纳不一致格式配置文件的时候,很不难招惹混淆。假若运用三个统一的法门对其进展操作,岂不美哉。

  那里默许xml文件为:address.xml,存放在和读取的php文件一律级别目录,xml内容如下:

1、XML

  那里暗中同意xml文件为:address.xml,存放在和读取的php文件一律级别目录,xml内容如下:


 

如以下为读取xml文件中内容的言传身教:

 

技能方案

思路很简单,正是选用三个基类将配置文件的始末空虚出来,分歧配置文件有差异的落到实处,对外统一调用方法。最伊始,打算自个儿写贰个,后来对照ini与xml的时候(最起首并未把json考虑进来,自身用它来做布置文件的门类较少),发现xml完全能够代替ini文件的叙述,直接用xml不是更好?

于是方案就成为了用xml作为最基础的数据对象,其余安顿文件转换来xml实行操作

<?xml version="1.0" encoding="utf-8"?>
<note>
    <name>简庆旺</name>
    <address>福建省漳州市南靖县梅林镇官洋村</address>
    <tel>17095921320</tel>
    <code>363609</code>
    <school>
        <highschool>
            <name>永定一中</name>
            <address>福建省龙岩市永定区91路</address>
        </highschool>
        <university>
            <name>吉首大学</name>
            <address>湖南省吉首市人民南路120号</address>
        </university>
    </school>

</note>
<?xml version="1.0" encoding="UTF-8"?>
<conf>
    <gui>0</gui>
    <theme>matrix</theme>
    <urls>
        <url>http:://www.url1.com</url>
        <url>http:://www.url2.com</url>
        <url>http:://www.url3.com</url>
        <url></url>
    </urls>
    <clock_style>24.35</clock_style>
</conf>

#include <cstdio>
#include <string>
#include <iostream>
using std::string;
#include "boost/property_tree/ptree.hpp"
#include "boost/property_tree/xml_parser.hpp"
#include "boost/typeof/typeof.hpp"
#include "boost/optional.hpp"
using namespace boost::property_tree;

int main()
{
    ptree pt;
    read_xml("conf.xml", pt);

    boost::optional<int> op = pt.get_optional<int>("conf.gui");//使用get_optional()获得节点,不存在则op为空
    if (op)
    {
        int i = op.get();
    }

    string str1 = pt.get<string>("conf.theme", "");//使用get()获得节点,不存在则返回""

    boost::optional<ptree&> child_null_test = pt.get_child_optional("conf.urls");
    if (child_null_test)
    {
        BOOST_AUTO(child, pt.get_child("conf.urls"));
        for (BOOST_AUTO(pos, child.begin()); pos != child.end(); ++pos)
        {
            string str = pos->second.get_value<string>();
            std::cout << str << std::endl;
        }
    }

    string str = pt.get("conf.clock_style", "");
}
<?xml version="1.0" encoding="utf-8"?>
<note>
    <name>简庆旺</name>
    <address>福建省漳州市南靖县梅林镇官洋村</address>
    <tel>17095921320</tel>
    <code>363609</code>
    <school>
        <highschool>
            <name>永定一中</name>
            <address>福建省龙岩市永定区91路</address>
        </highschool>
        <university>
            <name>吉首大学</name>
            <address>湖南省吉首市人民南路120号</address>
        </university>
    </school>

</note>

XDocument VS XmlDocment

不解释,直接看图。

亚洲必赢官网 1

PHP学习笔记,通用配置文件读写类与格式转换。 

以下为向xml文件添加内容:

 

ini <-> xml

ini文件构造相比较简单,常见的ini有以下几条标准:

  1. 注脚以;开端,一贯到行尾;
  2. 项目项用[]包围,占据一整行;
  3. 体系项下能够有多少个布局项,直到下3个档次项或EOF结束;
  4. 配置项格式:key=value

ini格式是二级配置结构:体系>key。通过品种和key就足以唯一获得3个值。

public static XDocument ToXml(this string[] iniStr)
{
    //ini没有根节点是不能直接转成xml的。
    XDocument xdoc = new XDocument(new XElement("G" + Guid.NewGuid().ToString("N")));
    XElement node = xdoc.Root;
    foreach (var line in iniStr)
    {
        var cline = line.Trim();
        if (string.IsNullOrWhiteSpace(cline)) continue;
        switch (line[0])
        {
            case ';':
                node.Add(new XComment(cline.Substring(1)));
                break;
            case '[':
                node = new XElement(cline.Substring(1, line.Length - 2));
                xdoc.Root.Add(node);
                break;
            case '\r':
                break;
            default:
                int index = cline.IndexOf('=');
                if (index < 1)
                {
                    throw new InvalidOperationException("Property does not contains '=' operator");
                }
                node.Add(new XElement(cline.Substring(0, index).Trim(), cline.Substring(index + 1)));
                break;
        }

    }
    return xdoc;
}

ini适合相比较简单的陈设读取,文件可读性强,读写也简单;而xml具有一种类结构,复杂,还有dtd,xslt什么的,相对来说相比较周到。由此,从xml转成ini,供给xml符合ini二级结构,详见
源代码中的IniExtensions类。

xml读取措施一:

    ptree pt;
    read_xml("conf.xml", pt);
    pt.add("conf.urls.url", "http://www.url4.com");
    write_xml("conf.xml", pt);

xml读取措施一:

xml <-> json

json在前者不要太火,用途广泛,占用空间小,机器也较好辨认。可是出于最初阶没考虑到json,就先上了xml的船,也懒得去想是否json作为基础结构更好了,先转移json到xml吧。
json与xml互转:直接用Newtonsoft.Json就足以了。使用SerializeXNodeDeserializeXNode就能够做到更换。

留意,xml与json互转,有局地地点供给小心。

  • xml的品质,转成json会加上前缀“@”
  • xml假若带证明的话,转成json就有前缀“?”
  • xml同级相同名称的要素在json中会组合贰个数组
  • xml的某一流唯有3个要素时,若是急需转成数组,须求添加json:Array='true'属性

考虑更换都在中间,读取json->xml->保存json。这几个流程不要求考虑以上难题。

//json没有根节点是不能直接转成xml的。
private static XDocument DecorateJson(string jsonStr)
{
    return JsonConvert.DeserializeXNode(jsonStr, "G" + Guid.NewGuid().ToString("N"));
}
<?php

$xml = simplexml_load_file('address.xml');
//输出下,内容是个对象
var_dump($xml);
echo ("<br/>");
//读取到简庆旺
echo $xml->name;
echo ("<br/>");
//读取到永定一中
echo $xml->school->highschool->name;
?>

以下为修改xml中内容:

<?php

$xml = simplexml_load_file('address.xml');
//输出下,内容是个对象
var_dump($xml);
echo ("<br/>");
//读取到简庆旺
echo $xml->name;
echo ("<br/>");
//读取到永定一中
echo $xml->school->highschool->name;
?>

打包难点

xml必要必须有且只有三个根节点,那或多或少,ini不满意,json有的不知足,因而要求足够四个暗中认可根节点来处理那几个标题。

为了防止配置项目和节点名称冲突,使用Guid.NewGuid()来获取不重复的值,由于xml供给成分名称不能够以数字先河,所以人为添加3个“G”前缀,感觉不是很优雅,有法子还请报告亚洲必赢官网,~

亚洲必赢官网 2

ptree pt;
    read_xml("conf.xml", pt);
    pt.put("conf.gui", 99);
    write_xml("conf.xml", pt);

亚洲必赢官网 3

操作配置文件

随便文件类型是什么,都用代表贰个目的表示1个陈设文件。由于使用了XDocment,那么使用linq是相比一贯的选项。然则考虑到读取配置的时候,一般用户都知情要求读取的种类,使用查询反而不是很直观。

那边小编利用XPathXPath是一门在 XML 文书档案中查找音信的语言。X帕特h
可用来在 XML
文书档案中对成分和性质进行遍历
。相关资料能够瞻仰http://www.w3school.com.cn/xpath。

XPath的用法很粗大略,对简易的安排项就和文件路径一样。那里笔者利用索引器来展开多少读取配置,也提供了GetValue和SetValue方法。

public void Test1()
{
    string str = @";时间单位为ms
[Dynamic]
Interval = 5
Delay = 4000

[Default]
Interval = 5
";
    System.IO.File.WriteAllText("test.ini", str);
    // e.g. "//config/general/interval" 从任意节点开始,检索config节点下general节点下的interval节点
    //     "/config/tick[@type='origin']" 从根节点检索config节点下,属性type='origin'的tick节点(只对XML)
    ConfigManager config = new ConfigManager("test.ini");
    Assert.Equal("5", config[@"//Default/Interval"]);
    Assert.Equal("5", config.GetValue("Default", "Interval"));
}

对上述配置,能够直接利用”//Delay”获得Delay的值(没有重名),对层级较深的配备,用户不要求关爱别的细节,直切正题,这么用依旧很舒心的~

 xml读取措施二:

以下为新建1个xml文件或打开2个xml并将里面包车型客车情节清除:

 xml读取措施二:

完全代码

一体化代码在github上,能够辅助.net framework/.net core/xamarin。

对应当nuget包,搜索nuget或许使用

Install-Package UnifiedConfig

即可将引用添加到项目。

 

ptree pt;
    pt.put("conf.gui", 0);
    write_xml("conf.xml", pt);

 

特性

  • 布局文件统一操作接口(读取,修改,保存)
  • 可进行配置项目协助
  • 活动测算文件类型

节点的习性保存在节点的<xmlattr>中,节点的申明保存在节点的<xmlcomment>中,获取示例如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<conf><!--conf comment-->
    <gui>1</gui>
    <theme id="001">matrix</theme>
    <urls><!--urls comment-->
    </urls>
</conf>

ptree pt;
    read_xml("conf.xml", pt);
    boost::optional<string> op = pt.get_optional<string>("conf.<xmlcomment>");
    if (op)
    {
        string strCommentConf = op.get();
    }
    op = pt.get_optional<string>("conf.urls.<xmlcomment>");
    if (op)
    {
        string strCommentUrls = op.get();
    }
    op = pt.get_optional<string>("conf.theme.<xmlattr>.id");
    if (op)
    {
        string strAttr = op.get();
    }

 2、JSON

使用property_tree解析json与解析xml的接口方法基本相同,分化的位置是读取json文件使用read_json,写入json文件使用write_json,如下示例:

 

{
    "conf":
    {
        "gui": 1,
        "theme": "matrix",
        "urls":
        {
            "url": "http://www.url1.com",
            "url": "http://www.url2.com",
            "url": "http://www.url3.com"
        },
        "clock_style": 24
    }
}

 

#include <cstdio>
#include <string>
#include <iostream>
using std::string;
#include "boost/property_tree/ptree.hpp"
#include "boost/property_tree/json_parser.hpp"
#include "boost/typeof/typeof.hpp"
#include "boost/optional.hpp"
using namespace boost::property_tree;

int main()
{
    ptree pt;
    read_json("conf.json", pt);

    boost::optional<int> op = pt.get_optional<int>("conf.gui");//不存在则op为空
    if (op)
    {
        int i = op.get();
        int a = 0;
    }

    string str1 = pt.get<string>("conf.theme", "");

    boost::optional<ptree&> child_null_test = pt.get_child_optional("conf.urls");
    if (child_null_test)
    {
        BOOST_AUTO(child, pt.get_child("conf.urls"));
        for (BOOST_AUTO(pos, child.begin()); pos != child.end(); ++pos)
        {
            string str = pos->second.get_value<string>();
            std::cout << str << std::endl;
        }
    }

    string str = pt.get("conf.clock_style", "");

    return getchar();
}

 

网站地图xml地图