一、属性文件
1.1 特殊文件概述
前面学习了IO流,知道IO流是用来读、写文件中的数据。但是接触到的文件都是普通的文本文件,普通的文本文件里面的数据是没有任何格式规范的,用户可以随意编写,如下图所示。
像这种普通的文本文件,没有任何规律可言,不方便程序对文件中的数据信息处理。
在以后的Java开发过程中还会遇到一些特殊的文本文件,这些文件是有一些格式要求的,方便程序对文件中的数据进行处理。
比如,后面我们会用到两种特殊的文本文件,一种是properties文件,还有一种是xml文件。如下图所示。
1.2为什么需要使用特殊文件
- 后缀为.properties的文件,称之为属性文件,它可以很方便的存储一些类似于键值对的数据。经常当做软件的配置文件使用。
- 而xml文件能够表示更加复杂的数据关系,比如要表示多个用户的用户名、密码、家乡、性别等。在后面,也经常当做软件的配置文件使用。
现在,学习特殊的文件主要学习什么呢? 主要学习以下的三点
二、Properties属性文件
学习Properties这种属性文件。首先要掌握属性文件的格式:
- 属性文件后缀以
.properties
结尾 - 属性文件里面的每一行都是一个键值对,键和值中间用=隔开。比如:
admin=123456
#
表示这样是注释信息,是用来解释这一行配置是什么意思。- 每一行末尾不要习惯性加分号,以及空格等字符;不然会把分号,空格会当做值的一部分。
- 键不能重复,值可以重复
接下来,我们学习如何读取属性文件中的数据,介绍一个叫Properties.
1.Properties是什么?
Properties是Map接口下面的一个实现类,所以Properties也是一种双列集合,用来存储键值对。 但是一般不会把它当做集合来使用。
2.Properties核心作用?
Properties类的对象,用来表示属性文件,可以用来读取属性文件中的键值对。
- 使用Properties读取属性文件中的键值对,需要用到的方法如下。
实用Properties读取属性文件的步骤如下
1、创建一个Properties的对象出来(键值对集合,空容器)
2、调用load(字符输入流/字节输入流)方法,开始加载属性文件中的键值对数据到properties对象中去
3、调用getProperty(键)方法,根据键取值
代码如下:
/**
* 目标:掌握使用Properties类读取属性文件中的键值对信息。
*/
public class PropertiesTest1 {
public static void main(String[] args) throws Exception {
// 1、创建一个Properties的对象出来(键值对集合,空容器)
Properties properties = new Properties();
System.out.println(properties);
// 2、开始加载属性文件中的键值对数据到properties对象中去
properties.load(new FileReader("properties-xml-log-app\\src\\users.properties"));
System.out.println(properties);
// 3、根据键取值
System.out.println(properties.getProperty("赵敏"));
System.out.println(properties.getProperty("张无忌"));
// 4、遍历全部的键和值。
//获取键的集合
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
//再根据键获取值
String value = properties.getProperty(key);
System.out.println(key + "---->" + value);
}
properties.forEach((k, v) -> {
System.out.println(k + "---->" + v);
});
}
}
- 使用Properties往属性文件中写键值对,需要用到的方法如下
往Properties属性文件中写键值对的步骤如下
1、先准备一个.properties属性文件,按照格式写几个键值对
1、创建Properties对象出来,
2、调用setProperty存储一些键值对数据
3、调用store(字符输出流/字节输出流, 注释),将Properties集合中的键和值写到文件中
注意:第二个参数是注释,必须得加;
先准备一个users.properties
属性文件,如下图所示
接下来,编写代码读取上面的属性文件。代码如下:
public class PropertiesTest2 {
public static void main(String[] args) throws Exception {
// 1、创建Properties对象出来,先用它存储一些键值对数据
Properties properties = new Properties();
properties.setProperty("张无忌", "minmin");
properties.setProperty("殷素素", "cuishan");
properties.setProperty("张翠山", "susu");
// 2、把properties对象中的键值对数据存入到属性文件中去
properties.store(new FileWriter("properties-xml-log-app/src/users2.properties")
, "i saved many users!");//该管道不需要手动关闭,因为作为参数传递给函数,函数生命周期到了之后会自动关闭管道
}
}
案例:遍历文件,判断是否存在键为“李方”的值,如果有就将值改为18。
三、XML文件
在上一节学习了properties属性文件。接下来再学习一种在开发中经常使用的文件,叫做xml文件。介绍一下,什么是xml文件,然后再来学习如何读取xml文件中的数据。
3.1 XML文件概述
首先,我们来认识一下,什么是XML?
XML是可扩展的标记语言,意思是它是由一些标签组成 的,而这些标签是自己定义的。本质上一种数据格式,可以用来表示复杂的数据关系。
XML文件有如下的特点:
- XML中的
<标签名>
称为一个标签或者一个元素,一般是成对出现的。 - XML中的标签名可以自己定义(可扩展),但是必须要正确的嵌套
- XML中只能有一个根标签。
- XML标准中可以有属性
- XML必须第一行有一个文档声明,格式是固定的
<?xml version="1.0" encoding="UTF-8"?>
- XML文件必须是以.xml为后缀结尾
如下图所示
接下,同学们可以跟着步骤新建一个XML文件,试试!
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 注释:以上抬头声明必须放在第一行,必须有 -->
<!-- 根标签只能有一个 -->
<users>
<user id="1" desc="第一个用户">
<name>张无忌</name>
<sex>男</sex>
<地址>光明顶</地址>
<password>minmin</password>
</user>
<people>很多人</people>
<user id="2">
<name>敏敏</name>
<sex>女</sex>
<地址>光明顶</地址>
<password>wuji</password>
</user>
</users>
上面XML文件中的数据格式是最为常见的,标签有属性、文本、还有合理的嵌套。XML文件中除了写以上的数据格式之外,还有一些特殊的字符不能直接写。
-
像
<,>,&
等这些符号不能出现在标签的文本中,因为标签格式本身就有<>,会和标签格式冲突。如果标签文本中有这些特殊字符,需要用一些占位符代替。
< 表示 < > 表示 > & 表示 & ' 表示 ' " 表示 "
<data> 3 < 2 && 5 > 4 </data>
-
如果在标签文本中,出现大量的特殊字符,不想使用特殊字符,此时可以用CDATA区,格式如下
<data1> <![CDATA[ 3 < 2 && 5 > 4 ]]> </data1>
最后,聊聊XML在实际开发中有什么作用?
关于XML是什么,以及XML的格式,还有XML有什么作用,就先认识到这里。
3.2 XML解析1
使用程序读取XML文件中的数据,称之为XML解析。这里并不需要我们自己写IO流代码去读取xml文件中的数据。其实有很多开源的,好用的XML解析框架,最知名的是DOM4J(第三方开发的)
由于DOM4J是第三方提供的,所以需要把第三方提供的Jar包导入到自己的项目中来,才可以使用。具体步骤如下:
DOM4J解析XML文件的思想是:文档对象模型(意思是把整个XML文档、每一个标签、每一个属性都等都当做对象来看待)。Dowument对象表示真个XML文档、Element对象表示标签(元素)、Attribute对象表示属性、标签中的内容就是文本
DOM4J解析XML需要用到的方法如下图所示
XML解析的过程,是从根元素开始,从外层往里层解析。 我们先把Document对象,和根元素获取出来
public class Dom4JTest1 {
public static void main(String[] args) throws Exception {
// 1、创建一个Dom4J框架提供的解析器对象
SAXReader saxReader = new SAXReader();
// 2、使用saxReader对象把需要解析的XML文件读成一个Document对象。
Document document =
saxReader.read("properties-xml-log-app\\src\\helloworld.xml");
// 3、从文档对象中解析XML文件的全部数据了
Element root = document.getRootElement();
System.out.println(root.getName());
}
}
3.3 XML解析2
获取到XML文件的根元素之后,接下来,就可以用根元素在获取到它里面的子元素(包括子标签、表属性等)。需要用到的方法如下图所示
接下来,把上面的方法先一个一个的演示一下。
public class Dom4JTest1 {
public static void main(String[] args) throws Exception {
// 1、创建一个Dom4J框架提供的解析器对象
SAXReader saxReader = new SAXReader();
// 2、使用saxReader对象把需要解析的XML文件读成一个Document对象。
Document document =
saxReader.read("properties-xml-log-app\\src\\helloworld.xml");
// 3、从文档对象中解析XML文件的全部数据了
Element root = document.getRootElement();
System.out.println(root.getName());
// 4、获取根元素下的全部一级子元素。
// List<Element> elements = root.elements();
List<Element> elements = root.elements("user");
for (Element element : elements) {
System.out.println(element.getName());
}
// 5、获取当前元素下的某个子元素。
Element people = root.element("people");
System.out.println(people.getText());
// 如果下面有很多子元素user,默认获取第一个。
Element user = root.element("user");
System.out.println(user.elementText("name"));
// 6、获取元素的属性信息呢?
System.out.println(user.attributeValue("id"));
Attribute id = user.attribute("id");
System.out.println(id.getName());
System.out.println(id.getValue());
List<Attribute> attributes = user.attributes();
for (Attribute attribute : attributes) {
System.out.println(attribute.getName() + "=" + attribute.getValue());
}
// 7、如何获取全部的文本内容:获取当前元素下的子元素文本值
System.out.println(user.elementText("name"));
System.out.println(user.elementText("地址"));
System.out.println(user.elementTextTrim("地址")); // 取出文本去除前后空格
System.out.println(user.elementText("password"));
Element data = user.element("data");
System.out.println(data.getText());
System.out.println(data.getTextTrim()); // 取出文本去除前后空格
}
}
3.4 XML文件写入
在前面我们已经学习了XML解析,意思就是使用程序把XML文件中的数据读取出来。反过来能不能往XML文件中写入数据呢? 答案是可以的。
DOM4J也提供了往XML文件中写标签的方法,但是用起来比较麻烦。这里不建议使用
我们自己使用StringBuilder按照标签的格式拼接,然后再使用BufferedWriter写到XML文件中去就可以了。
public class Dom4JTest2 {
public static void main(String[] args) {
// 1、使用一个StringBuilder对象来拼接XML格式的数据。
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
sb.append("<book>\r\n");
sb.append("\t<name>").append("从入门到跑路").append("</name>\r\n");
sb.append("\t<author>").append("dlei").append("</author>\r\n");
sb.append("\t<price>").append(999.99).append("</price>\r\n");
sb.append("</book>");
try (
BufferedWriter bw = new BufferedWriter(new FileWriter("properties-xml-log-app/src/book.xml"));
){
bw.write(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.5 XML约束(了解)
首先,说一些什么是XML约束?
XML约束指的是限制XML文件中的标签或者属性,只能按照规定的格式写。
比如我在项目中,想约束一个XML文件中的标签只能写<书>、<书名>、<作者>、<售价>这几个标签,如果写其他标签就报错。
怎么才能达到上面的效果呢?有两种约束技术,一种是DTD约束、一种是Schame约束。
-
DTD约束案例
如下图所示book.xml中引入了DTD约束文件,book.xml文件中的标签就受到DTD文件的约束
DTD文件解释
<!ELEMENT 书架(书+)> 表示根标签是<书架>,并且书架中有子标签<书>
<!ELEMENT 书(书名、作者、售价)> 表示书是一个标签,且书中有子标签<书名>、<作者>、<售价>
<!ELEMENT 书名(#PCDATA)> 表示<书名>是一个标签,且<书名>里面是普通文本
<!ELEMENT 作者(#PCDATA)> 表示<作者>是一个标签,且<作者>里面是普通文本
<!ELEMENT 售价(#PCDATA)> 表示<售价>是一个标签,且<售价>里面是普通文本
- Schame约束案例
如下图所示,左边的book2.xml文件就受到右边schame文件(.xsd结尾的文件)的约束。