目录
propeties属性文件,XML文件
为什么要用这些特殊文件?用于存储多个用户的用户名、密码,按键值对存储
- 后缀为.properties的文件,称之为属性文件,它可以很方便的存储一些类似于键值对的数据。经常当做软件的配置文件使用。
- 而xml文件能够表示更加复杂的数据关系,比如要表示多个用户的用户名、密码、家乡、性别等。在后面,也经常当做软件的配置文件使用。
日志技术:把程序运行的信息,记录到文件中,方便程序员定位bug、并了解程序的执行情况等
特点作用
使用程序读取它们里面的数据
使用程序把数据存储到这些文件里
特殊文件:Properties属性文件
特点、作用
- 只能是键值对
- 键不能重复
- 文件后缀一般是.properties结尾的
properties
- 是一个Map集合(键值对集合),但是我们一般不会当集合使用。
- 核心作用:Properties是用来代表属性文件的,通过Properties可以读写属性文件里的内容。
使用Properties读取属性文件里的键值对数据
构造器 | 说明 |
---|---|
public Properties() | 用于构建Properties集合对象(空容器) |
常用方法 | 说明 |
---|---|
public void load(InputStream is) | 通过字节输入流,读取属性文件里的键值对数据 |
public void load(Reader reader) | 通过字符输入流,读取属性文件里的键值对数据 |
public String getProperty(String key) | 根据键获取值(其实就是get方法的效果) |
public Set stringPropertyNames() | 获取全部键的集合(其实就是ketSet方法的效果) |
实用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);
}
//也可以使用forEach循环取出
properties.forEach((k, v) -> {
System.out.println(k + "---->" + v);
});
}
}
使用properties把键值对数据写到属性文件中去
需要用到的方法如下:
构造器 | 说明 |
---|---|
public Properties() | 用于构建Properties集合对象(空容器) |
常用方法 | 说明 |
---|---|
public Object setProperty(String key, String value) | 保存键值对数据到Properties对象中去。 |
public void store(OutputStream os, String comments) | 把键值对数据,通过字节输出流写出到属性文件里去 |
public void store(Writer w, String comments) | 把键值对数据,通过字符输出流写出到属性文件里去 |
store()会自动关闭管道,使用后不用手动关闭
往Properties属性文件中写键值对的步骤如下
1、先准备一个.properties属性文件,按照格式写几个键值对
2、创建Properties对象出来,
3、调用setProperty存储一些键值对数据
4、调用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!");
}
}
运行上面的代码,user2.properties
配置文件打开效果如下图所示。
案例
读取属性文件,判断是否存在"user2",如存在,将value改成“asasas”
package specialFile;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Properties;
public class PropertiesTest3 {
public static void main(String[] args) throws Exception {
//1、加载属性文件的键值对到程序中来
Properties properties = new Properties();
//2、开始加载
properties.load(new FileReader("oop/src/specialFile/user.txt"));
//3、判断是否包含user2这个键
if (properties.containsKey("user2")) {
properties.setProperty("user2","asasas");
}
//4、把properties对象的键值对数据重新写到属性文件中去
properties.store(new FileWriter("oop/src/specialFile/user.txt"),"success!");
}
}
特殊文件:XML文件
概述
XML( 全称EXtensible Markup Language, 可扩展标记语言 )
可扩展的意思就是里面的标签可以自己定义。
本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。
XML的特点
- XML中的“<标签名>” 称为一个标签或一个元素,一般是成对出现的。
- XML中的标签名可以自己定义(可扩展),但必须要正确的嵌套。
- XML中只能有一个根标签。
- XML中的标签可以有属性。
- 如果一个文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般要写成.xml。
XML的创建
就是创建一个XML类型的文件,要求文件的后缀必须使用xml,如hello_world.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> //Out: 3 < 2 && 5 > 4
-
如果在标签文本中,出现大量的特殊字符,不想使用特殊字符,此时可以用CDATA区,格式如下
<data1> <![CDATA[ 3 < 2 && 5 > 4 ]]> </data1>
XML的作用和应用场景
本质是一种数据格式,可以存储复杂的数据结构,和数据关系。
应用场景:经常用来做为系统的配置文件;或者作为一种特殊的数据结构,在网络中进行传输。
读取XML文件中的数据
使用程序读取XML文件中的数据,也就是解析XML文件。
注意:程序员并不需要自己写原始的IO流代码来解析XML,难度较大!也相当繁琐!
有很多开源的,好用的,解析XML的框架,最知名的是:Dom4j(第三方研发的)
步骤:使用Dom4J解析出XML文件
需求:使用Dom4J把一个XML文件的数据进行解析
分析:
- 下载Dom4j框架,官网下载。(-sources.jar可以看源码,-javadoc.jar可以看使用文档)
- 在项目中创建一个文件夹:lib
- 将dom4j-2.1.3.jar文件复制到 lib 文件夹
- 在jar文件上点右键,选择 Add as Library -> 点击OK
- 在类中导包使用
DOM4J解析XML文件的思想:文档对象模型
DOM4J解析XML文件的思想是:文档对象模型(意思是把整个XML文档、每一个标签、每一个属性都等都当做对象来看待)。Dowument对象表示真个XML文档、Element对象表示标签(元素)、Attribute对象表示属性、标签中的内容就是文本。
Dom4j解析XML - 得到Document对象
- SAXReader:Dom4j提供的解析器,可以认为是代表整个Dom4j框架
构造器/方法 | 说明 |
---|---|
public SAXReader() | 构建Dom4J的解析器对象 |
public Document read(String url) | 把XML文件读成Document对象 |
public Document read(InputStream is) | 通过字节输入流读取XML文件 |
- Document
方法名 | 说明 |
---|---|
Element getRootElement() | 获得根元素对象 |
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());
}
}
获取到XML文件的根元素之后,接下来,就可以用根元素在获取到它里面的子元素(包括子标签、表属性等)。需要用到以下方法:
方法名 | 说明 |
---|---|
public String getName() | 得到元素名字 |
public List elements() | 得到当前元素下所有子元素 |
public List elements(String name) | 得到当前元素下指定名字的子元素返回集合 |
public Element element(String name) | 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个 |
public String attributeValue(String name) | 通过属性名直接得到属性值 |
public String elementText(子元素名) | 得到指定名称的子元素的文本 |
public String getText() | 得到文本 |
代码如下:
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()); //Out:很多人
// 如果下面有很多子元素user,默认获取第一个。
Element user = root.element("user");
System.out.println(user.elementText("name")); //Out: 张无忌
// 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());
} //Out: id="1" desc="第一个用户"
// 7、如何获取全部的文本内容:获取当前元素下的子元素文本值
System.out.println(user.elementText("name"));
//Out:张无忌
System.out.println(user.elementText("地址"));
//Out:光明顶
System.out.println(user.elementTextTrim("地址")); // 取出文本去除前后空格
System.out.println(user.elementText("password"));
Element data = user.element("data");
System.out.println(data.getText()); //Out: 3 < 2 && 5 > 4
System.out.println(data.getTextTrim()); // 取出文本去除前后空格
}
}
对应XML文件如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 注释:以上抬头声明必须放在第一行,必须有 -->
<!-- 根标签只能有一个 -->
<users>
<user id="1" desc="第一个用户">
<name>张无忌</name>
<sex>男</sex>
<地址>光明顶</地址>
<password>minmin</password>
<data> 3 < 2 && 5 > 4 </data>
<data1>
<![CDATA[
3 < 2 && 5 > 4
]]>
</data1>
</user>
<people>很多人</people>
<user id="2">
<name>敏敏</name>
<sex>女</sex>
<地址>光明顶</地址>
<password>wuji</password>
<data> 3 < 2 && 5 > 4 </data>
<data1>
<![CDATA[
3 < 2 && 5 > 4
]]>
</data1>
</user>
</users>
把数据写出到XML文件中去
可以继续用dom4j实现,但是不建议。
推荐直接把程序中的数据拼接成XML格式,然后用IO流写出去
package com.itheima.d2_xml;
import java.io.BufferedWriter;
import java.io.FileWriter;
/**
* 目标:如何使用程序把数据写出到 XML文件中去。
* <?xml version="1.0" encoding="UTF-8" ?>
* <book>
* <name>从入门到跑路</name>
* <author>dlei</author>
* <price>999.9</price>
* </book>
*/
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();
}
}
}
补充知识:约束XML文件的编写[了解]
就是限制XML文件只能按照某种格式进行书写。
约束文档:
专门用来限制xml书写格式的文档,比如:限制标签、属性应该怎么写。
约束文档的分类:DTD文档,Schema文档
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
<!ELEMENT 书架(书+)> 表示根标签是<书架>,并且书架中有子标签<书>
<!ELEMENT 书(书名、作者、售价)> 表示书是一个标签,且书中有子标签<书名>、<作者>、<售价>
<!ELEMENT 书名(#PCDATA)> 表示<书名>是一个标签,且<书名>里面是普通文本
<!ELEMENT 作者(#PCDATA)> 表示<作者>是一个标签,且<作者>里面是普通文本
<!ELEMENT 售价(#PCDATA)> 表示<售价>是一个标签,且<售价>里面是普通文本
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM "data.dtd">
<书架>
<书>
<书名>从入门到删库</书名>
<作者>小猫</作者>
<售价>很便宜</售价>
</书>
<书>
<书名>从入门到删库</书名>
<作者>小猫</作者>
<售价>9.9</售价>
</书>
<书>
<书名>从入门到删库</书名>
<作者>小猫</作者>
<售价>9.9</售价>
</书>
</书架>
<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itcast.cn"
elementFormDefault="qualified" >
<!-- targetNamespace:申明约束文档的地址(命名空间)-->
<element name='书架'>
<!-- 写子元素 -->
<complexType>
<!-- maxOccurs='unbounded': 书架下的子元素可以有任意多个!-->
<sequence maxOccurs='unbounded'>
<element name='书'>
<!-- 写子元素 -->
<complexType>
<sequence>
<element name='书名' type='string'/>
<element name='作者' type='string'/>
<element name='售价' type='double'/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
<?xml version="1.0" encoding="UTF-8" ?>
<书架 xmlns="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.itcast.cn data.xsd">
<!-- xmlns="http://www.itcast.cn" 基本位置
xsi:schemaLocation="http://www.itcast.cn books02.xsd" 具体的位置 -->
<书>
<书名>从入门到删除</书名>
<作者>dlei</作者>
<售价>9.9</售价>
</书>
<书>
<书名>从入门到删除</书名>
<作者>dlei</作者>
<售价>0.9</售价>
</书>
</书架>
如下图所示,左边的book2.xml文件就受到右边schame文件(.xsd结尾的文件)的约束。
日志技术
概述
想搞清楚什么是日志,其实可以通过下面几个问题来了解的。
- 系统系统能记住某些数据被谁操作,比如被谁删除了?
- 想分析用户浏览系统的具体情况,比如挖掘用户的具体喜好?
- 当系统在开发中或者上线后出现了Bug,崩溃了,该通过什么去分析,定位Bug?
而日志就可以帮我们解决以上的问题。 用来记录程序运行过程中的信息,并可以进行永久存储。 所以日志就好比生活中的日记,日记可以记录生活中的点点滴滴;而程序中的日志,通常就是一个文件,里面记录了程序运行过程中产生的各种数据。
之前记录日志的方案是用输出语句,这样做有以下弊端:
- 日志会展示在控制台
- 不能更方便的将日志记录到其他的位置(文件,数据库)
- 想取消日志,需要修改源代码才可以完成
日志技术
- 可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。
- 可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改。
日志技术体系、Logback日志框架的概述
日志技术的体系结构:
日志框架:牛人或者第三方公司已经做好的实现代码,后来者直接可以拿去使用。
日志接口:设计日志框架的一套标准,日志框架需要实现这些接口。
注意1:因为对Commons Logging接口不满意,有人就搞了SLF4J;因为对Log4j的性能不满意,有人就搞了Logback。
注意2:Logback是基于slf4j的日志规范实现的框架。
所以这里推荐使用Logback
Logback日志框架官方网站:https://logback.qos.ch/index.html
Logback日志框架有以下几个模块:
想使用Logback日志框架,至少需要在项目中整合如下三个模块:
- slf4j-api:日志接口
- logback-core:基础模块
- logback-classic:功能模块,它完整实现了slf4j API
Logback快速入门
本节需要使用Logback日志框架,纪录系统的运行信息。
实现步骤
①:将三个模块导入Logback框架到项目中去。(slf4j-api.jar, logback-core.jar, logback-classic.jar)复制到lib中,然后add as library
②:将Logback框架的核心配置文件logback.xml直接拷贝到src目录下(必须是src下)。
③:创建Logback框架提供的Logger对象,然后用Logger对象调用其提供的方法就可以记录系统的日志信息
public static final Logger LOGGER = LoggerFactory.getLogger(“类名");
开始记录日志,代码如下:
package com.itheima.d3_log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 目标:掌握LogBack日志框架的使用。
*/
public class LogBackTest {
// 创建一个Logger日志对象
public static final Logger LOGGER = LoggerFactory.getLogger("LogBackTest");
public static void main(String[] args) {
//while (true) {
try {
LOGGER.info("chu法方法开始执行~~~");
chu(10, 0);
LOGGER.info("chu法方法执行成功~~~");
} catch (Exception e) {
LOGGER.error("chu法方法执行失败了,出现了bug~~~");
}
//}
}
public static void chu(int a, int b){
LOGGER.debug("参数a:" + a);
LOGGER.debug("参数b:" + b);
int c = a / b;
LOGGER.info("结果是:" + c);
}
}
logback.xml文件如下(log文件会存储在红框位置中):
运行程序时,控制台记录的日志:
日志配置文件
核心配置文件logback.xml对Logback日志框架进行控制的。
- 可以配置日志的输出位置、输出格式的设置
通常可以设置2个输出日志的位置:一个是控制台、一个是系统文件中
- 可以选择开启日志(ALL),取消日志(OFF):
Logback设置日志级别
日志级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下(优先级依次升高):
日志级别 | 说明 |
---|---|
trace | 追踪,指明程序运行轨迹 |
debug | 调试,实际应用中一般将其作为最低级别,而 trace 则很少使用 |
info | 输出重要的运行信息,数据连接、网络连接、IO操作等等,使用较多 |
warn | 警告信息,可能会发生问题,使用较多 |
error | 错误信息, 使用较多 |
只有日志的级别是大于或等于核心配置文件配置的日志级别,才会被记录,否则不记录。