文章目录
XML 文件
前言
在我们编程过程中,我们都需要基于我们的程序对数据进行处理,以前接触的很多程序都是很“不实用”的,其最重要的原因就是:无法长期保存数据。
这时候我们就需要了解到“持久化”技术!
数据持久化就是将内存中的数据模型转化为存储模式,以及将存储模型转化为内存中数据模型的统称。数据模型可以是任何数据结构或者对象模型,存储模型可以是关系模型、XML、二进制流等。cmp 和 Hibernate 只是对象模型到关系模型之间转换的不同实现。
——摘自百度百科 / 数据持久化
这里所谓“存储模型”可以理解为:用文件的方式存储数据。
百度百科中所提到的三种基本存储模型:关系模型就是数据库技术;结构化数据文件存储技术就是 XML;第三种就是二进制流存储(主要在网络通信中传输数据,或本地数据的存储与读取)。
XML——可扩展标记语言
XML 概念
XML(Extensible Markup Language), 即:可扩展标记语言。
可扩展标记语言 (Extensible Markup Language, XML) ,标准通用标记语言的子集,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML是标准通用标记语言 可扩展性良好,内容与形式分离,遵循严格的语法要求,保值性良好等优点 。
在电子计算机中,标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种的信息比如文章等。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。是Internet环境中跨平台的、依赖于内容的技术,也是当今处理分布式结构信息的有效工具。早在1998年,W3C 就发布了XML1.0规范,使用它来简化Internet的文档信息传输。
——摘自 百度百科 可扩展标记语言
XML 书写规则及语法要求
XML 文件有着其严格的书写规则和语法要求。
标签
标签是为了能表达有一定意义的数据的起、止标记,分起始标签和结束标签,就像我们在 C 和 Java 程序中经常见到的{}。起止标签之间的文本成为内容。基本内容如下:
XML 标签遵循如下基本原则:
- 大小写敏感;
- 起止标签必须成对出现,且必须保持严格的顺序。
例如:
<student>
<id>03207076</id>
<student>
XML 标签属性
在开始标签中,可以通过 键 = 值 的形式定义一个或者多个属性。即,上述例子还可以写成:
<student id="03207076">HB</student>
其中,id = “03207076” 就是 student 标签的 id 属性。要注意的是,“=”后面的值必须要用双引号括起来。
XML 文档头
XML 文件应该以一个文档头开始的,如:
<?xml version="1.0”?>虽然文件头不是必须要求写的,但还是强烈建议使用文档头。
XML 根标签
XML 文件里的众多标签,都应该在一个根标签中书写。如:
<students>
<student id="03207076">HB</student>
</students>
XML 注释
XML 中的注释使用:
注释在解析 XML 时,将被忽略。
XML 文件示例
下面给出两种表达学生信息的 XML 文档内容。
格式一:
<?xml version="1.0" encoding="UTF-8"?>
<informations>
<information>
<stuId>03207076</stuId>
<name>HB</name>
<password>021001</password>
<sex>male</sex>
<birth>2002-10-20</birth>
<hobbies>
<hobby>编程</hobby>
<hobby>打篮球</hobby>
</hobbies>
<introduce>帅气阳光的男孩</introduce>
</information>
<information>
<stuId>2007011076</stuId>
<name>SQR</name>
<password>021020</password>
<sex>fmale</sex>
<birth>2002-10-01</birth>
<hobbies>
<hobby>弹扬琴</hobby>
<hobby>跳舞</hobby>
</hobbies>
<introduce>美女</introduce>
</information>
</informations>
格式二:
<?xml version="1.0" encoding="UTF-8"?>
<informations>
<information stuId="03207076" name="HB" password="123456" sex="male" birth="2002-10-20">
<hobbies>
<hobby>编程</hobby>
<hobby>打篮球</hobby>
</hobbies>
<introduce>帅气阳光的男孩</introduce>
</information>
<information stuId="2007011076" name="SQR" password="654321" sex="fmale" birth="2002-10-01">
<hobbies>
<hobby>弹扬琴</hobby>
<hobby>跳舞</hobby>
</hobbies>
<introduce>美女</introduce>
</information>
</informations>
第一种方式着重使用标签,第二种方式综合属性和标签。两种方式都可以表达学生信息,没有哪一种是标准方式,我个人比较喜欢用第二种。
XML 文档解析
Properties 文件
Properties 语法及书写
XML文件能够表示和在储层次结构的数据,功能很强大。但是,很多时候,我们编程所需要的数据往往都是只
由“键值对”构成的扁平数据。对于这样的数据,使用XML表达和存储,就有点小题大做了
对于键值对形式的数据,用Properties类型的文档处理再恰当不过了!Properties 文档相对XML文档要简单得多,直接就是由键值对组成的。
# '#'是注释,在解析时将会被忽略;
# properties 文件没有特定的文件头;
# 键值对之间用"="连接;
# 也可以用空格连接;
# 最大值
maxNum=30
# 最小值
minNum=2
# 增量
incNum=3
Properties 文档解析
首先先建立一个 Properties 文件;
max_client_count=30
port=4288
ip=192.168.1.1
auto_show=true
然后给出解析文档的代码:
public class TestParseProperties {
public static void main(String[] args) {
//初始化一个 Properties 对象;
Properties prop =new Properties();
//指定一个文件变成一个输入流;
InputStream is = TestParseProperties.class.getResourceAsStream("/something.cfg.properties");
try {
//通过 load 将这个输入流装载进来
prop.load(is);
//根据键获得值;
String strMaxClientCount = prop.getProperty("max_client_count");
int maxClientCount = Integer.parseInt(strMaxClientCount);
System.out.println(maxClientCount);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
这里这种方式,在需要数据的时候,才对数据进行load,一次一次的外存访问,会降低系统与运行效率,所以这里我们打算一次将数据从外存读入到内存,一次将数据全部 load ,来用空间换取时间,即占用大量的内存空间来换取内存访问的高速。
public class TestPropertiesTool {
public static void main(String[] args) {
HashMap<String,String> keyValuePool = new HashMap<>();
String configPath = "/something.cfg.properties";
InputStream is = TestParseProperties.class.getResourceAsStream(configPath);
if(is == null) {
return;
}
Properties properties = new Properties();
try {
properties.load(is);
for (Object key : properties.keySet()) {
String strKey = (String) key;
String value = properties.getProperty(strKey);
keyValuePool.put(strKey,value);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
String ip =keyValuePool.get("ip");
System.out.println(ip);
}
}
这里也是为我们后面的解析 Properties 的工具编写做铺垫。
Properties 解析器(工具)
在我们自己的 Util 中创建一个新类 PropertiesParser:
public class PropertiesParser {
private static final Map<String,String> valuePool = new HashMap<String,String>();
//上述静态成员的初始化语句,将在该类被初次加载时被执行,且只执行一次;
//或者说,这个 valuePool 是”单例“的
public PropertiesParser() {
}
public static void load(String propertiesPath) throws Exception {
InputStream inputStream = PropertiesParser.class.getResourceAsStream(propertiesPath);
if(inputStream == null) {
throw new Exception("Properties文件【" + propertiesPath + "】不存在!");
}
load(inputStream);
}
public static void load(InputStream inputStream) throws Exception {
Properties properties = new Properties();
properties.load(inputStream);
for (Object obj : properties.keySet()) {
String key = (String)obj;
String value = properties.getProperty(key);
valuePool.put(key,value);
}
}
public static String get(String key) {
return valuePool.get(key);
}
}
这就形成了我们的新工具 Properties 文件解析器,然后进行打包,导出 jar 包。
在之前所创建 Properties 文件的工程中导入 jar 包,进行测试:
import com.hb.util.PropertiesParser;
public class Test {
public static void main(String[] args) {
try {
PropertiesParser.load("/something.cfg.properties");
String ip = PropertiesParser.get("ip");
System.out.println(ip);
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出结果也是我们 Properties 文件中的 ip;
192.168.1.1