一、特殊文件
1. properties属性文件
1.1 properties属性文件
- 只能是键值对
- 键不能重复
- 文件后缀一般为.properties,但是只要格式正确,是键值对格式,后缀为txt等也可以
1.2 Properties集合
- Properties是一个Map集合(键值对集合),但是一般不会当作集合使用,仅仅用于读写properties属性文件。
- 核心作用:Properties类是用来代表属性文件的,通过Properties可以读写属性文件里的内容。
1.3.1 使用Properties读取properties属性文件
构造器 | 说明 |
---|---|
public Properties( ) | 创建内容为空的Properties集合对象 |
方法 | 说明 |
---|---|
public void load(InputStream is) | 通过字节输入流,将属性文件里的键值对数据注入到Properties集合中 |
public void load(Reader reader) | 通过字符输入流,将属性文件里的键值对数据注入到Properties集合中 |
public String getProperty(String key) | 根据键获取Properties集合中的值 |
public Set<String> stringPropertyNames( ) | 获取Properties集合中的所有键 |
# -*- coding: utf-8 -*-
admin=123456
周紫若=103
张无忌=129
姬发=100
public class Test1 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileReader("src/com/lmh/properties/users.properties"));
String value = properties.getProperty("admin");
System.out.println(value);//123456
//遍历的第一种方式
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
System.out.println(key + "--->" + properties.getProperty(key));
}
//遍历的第二种方式
properties.forEach((k, v) -> System.out.println(k + "--->" + v));
}
}
/*
admin--->123456
张无忌--->129
周紫若--->103
姬发--->100
admin--->123456
张无忌--->129
周紫若--->103
姬发--->100
*/
1.3.2 使用Properties将键值对写入properties属性文件
构造器 | 说明 |
---|---|
public Properties( ) | 创建内容为空的Properties集合对象 |
方法 | 说明 |
---|---|
public Object setProperty( String key,String value ) | 保存键值对数据到Properties对象中去 |
public void store( OutputStream os, String comments ) | 把Properties中的键值对数据通过字节输出流写出到属性文件里去,第二个参数为注释 |
public void store( Writer w , String comments ) | 把Properties中的键值对数据通过字符输出流写出到属性文件里去,第二个参数为注释 |
public class Test2 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.setProperty("admin", "123456");
properties.setProperty("张无忌", "129");
properties.store(new FileWriter("src/com/lmh/properties/test2.properties"),
"用户信息");
}
}
1.3.3 案例
将下面txt文件中的内容的李方对应的年龄修改为18
杨过=21
小龙女=38
郭靖=50
黄蓉=45
李方=35
郭芙=18
尹志平=30
public class Test3 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileReader("src\\com\\lmh\\properties\\a.txt"));
if (properties.containsKey("李方")) {// 判断是否包含指定的键
properties.setProperty("李方", "18");// 修改指定的键值对
System.out.println("修改后的键值对:" + properties);
}
properties.store(new FileWriter("src\\com\\lmh\\properties\\a.txt"), "");
}
}
2. XML文件(可扩展标记语言)
2.1 XML文件概述
本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。
2.1.1 XML文件的特点
-
XML中的“<标签名>”称为一个标签或一个元素,一般是成对出现的。
-
XML中的标签名可以自己定义(可扩展),但必须要正确的嵌套。
-
XML中只能有一个根标签
-
XML中的标签可以有属性并且可以有多个属性
-
<?xml version="1.0" encoding="UTF-8" ?> <!--上面的version,encoding即为属性,可以有多个--> <users> <!--下面的id即为属性,可以有多个--> <user id="1"> <name>张无忌</name> <age>18</age> </user> </users>
-
-
如果一个文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般要写成XML
2.1.2 XML文件的语法规则
- XML文件的后缀名为:xml,文档声明必须是第一行
- version: XML默认的版本号码、该属性是必须存在的
- encoding: 本XML文件的编码
- XML中可以定义注释信息:<!–注释内容–>
<?xml version="1.0" encoding="UTF-8" ?>
<!--注释内容写在该处-->
<!--下面的<users></users>为根标签,只能有一个-->
<users>
<!--下面的<user></user>为子标签,可以有多个-->
<user id="1">
<name>张无忌</name>
<sex>男</sex>
<age>18</age>
</user>
<user id="2">
<name>周芷若</name>
<sex>女</sex>
<age>16</age>
</user>
</users>
- XML中书写”<”、“&”等,可能会出现冲突,导致报错,此时可以用如下特殊字符替代
原符号 | 替代符号 |
---|---|
<(小于号) | < |
>(大于号) | > |
&(和) | & |
'(单引号) | ' |
‘’(引号) | " |
<?xml version="1.0" encoding="UTF-8" ?>
<users>
<user id="1">
<data1>
3 > 2 & 1 < 2
</data1>
</user>
</users>
- XML中可以写一个叫CDATA的数据区:<![CDATA[内容]]>,里面的内容可以任意写,不会报错
<?xml version="1.0" encoding="UTF-8" ?>
<users>
<user id="1">
<data2>
<![CDATA[
3 > 2 & 1 < 2
]]>
</data2>
</user>
</users>
2.1.3 XML文件的作用和应用场景
- 本质是一种数据格式,可以存储复杂的数据结构和数据关系
- 应用场景:经常用来做为系统的配置文件,或者作为一种特殊的数据结构,在网络中进行传输
2.2 解析XML文件
2.2.1 导入Dom4J框架(用于解析XML文件)
-
官网下载Dom4j对应的jar包
- 网址:dom4j官方地址
-
将jar包导入到项目中
- 将jar包复制到项目的lib文件夹下
- 在jar文件上点右键,将其加入library
2.2.2 使用Dom4J框架解析XML文件
- SAXReader对象:Dom4j提供的解析器,可以认为是代表整个Dom4j框架
- Document对象:代表SAXReader对象读取的xml文件
- Element对象:代表Document对象中的根标签或根元素对象
SAXReader构造器 | 说明 |
---|---|
public SAXReader( ) | 构建Dom4的解析器对象 |
SAXReader对象的方法 | 说明 |
---|---|
public Document read( String url ) | 把XML文件读成Document对象 |
public Document read( InputStream is ) | 通过字节输入流读取XML文件 |
Document对象的方法 | 说明 |
---|---|
Element getRootElement( ) | 获得Element对象 |
Element对象的方法 | 说明 |
---|---|
public String getName( ) | 获取标签或元素的名字 |
public List<Element> elements( ) | 获取当前标签或元素下所有子标签或子元素 |
public List<Element> elements( String name ) | 获取当前元素下指定名字的子元素集合 |
public Element element( String name ) | 得到当前元素下指定名字的子元素,如果有很多名字相同的子元素则返回第一个 |
public String attributeValue( String name ) | 通过属性的名直接得到属性的值 |
public Attribute attribute(String s ) | 获取当前Element对象的指定名称的属性的对象 |
public String elementText(子元素名 ) | 获取当前元素指定名称的子元素的文本 |
public String getText( ) | 获取当前元素的文本 |
public String getTextTrim( ) | 获取当前元素取出空格后的文本 |
<?xml version="1.0" encoding="UTF-8" ?>
<users>
<user id="1">
<name>张无忌</name>
<sex>男</sex>
<age>18</age>
<data1>
3 > 2 & 1 < 2
</data1>
<data2>
<![CDATA[
3 > 2 & 1 < 2
]]>
</data2>
</user>
<user id="2">
<name>周芷若</name>
<sex>女</sex>
<age>16</age>
</user>
<people> hhh</people>
</users>
public class Test1 {
public static void main(String[] args) throws Exception {
//创建SAXReader对象
SAXReader saxReader = new SAXReader();
//读取xml文件,返回Document对象
Document document
= saxReader.read("src/com/lmh/xml/a.xml");
//获取根标签的Element对象
Element rootElement = document.getRootElement();
//获取根标签的名字
String name = rootElement.getName();
System.out.println(name);
System.out.println("-------------------------------");
//获取根标签下的所有子标签或子元素的集合
List<Element> elements = rootElement.elements();
for (Element element : elements) {
System.out.println(element.getName());
}
System.out.println("-------------------------------");
//获取根标签下的指定名称的子标签或子元素的集合
List<Element> elements1 = rootElement.elements("user");
for (Element element : elements1) {
System.out.println(element.getName() + " " + element.attributeValue("id"));
}
System.out.println("-------------------------------");
//获取根标签下的指定名称的第一个子标签或子元素的Element对象
Element element = rootElement.element("user");
//通过属性名获取属性值
System.out.println(element.attributeValue("id"));
System.out.println("-------------------------------");
//获取属性的对象
Attribute id = element.attribute("id");
System.out.println(id.getName() + " " + id.getValue());
System.out.println("-------------------------------");
//获取当前元素中指定名称的子元素的文本
String text = element.elementText("sex");
System.out.println(text);
System.out.println("-------------------------------");
//获取当前元素的文本
Element people = rootElement.element("people");
System.out.println(people.getText());
System.out.println("-------------------------------");
//获取当前元素去掉空格后的文本
System.out.println(people.getTextTrim());
}
}
/*
users
-------------------------------
user
user
people
-------------------------------
user 1
user 2
-------------------------------
1
-------------------------------
id 1
-------------------------------
男
-------------------------------
hhh
-------------------------------
hhh
*/
2.3 将数据写入到XML文件(几乎不用)
直接使用字符串拼接成XML格式后使用IO流写入
/**
* 目标:将下列数据写出到 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();
}
}
}
2.4 约束XML文件的编写(了解即可)
限制XML文件只能按照某种格式进行书写
2.4.1 约束文档
专门用来限制x书写格式的文档,比如:限制标签、属性应该怎么写
2.4.2 约束文档的分类
(1)DTD文档
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM "data.dtd">
<!--上面的一行代码用于导入data.dtd约束-->
<书架>
<书>
<书名>从入门到删库</书名>
<作者>小猫</作者>
<售价>很便宜</售价>
</书>
<书>
<书名>从入门到删库</书名>
<作者>小猫</作者>
<售价>9.9</售价>
</书>
<书>
<书名>从入门到删库</书名>
<作者>小猫</作者>
<售价>9.9</售价>
</书>
</书架>
(2)Schema文档
<?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</售价>
</书>
</书架>
3. 日志技术
3.1 日志技术概述
- 可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)
- 可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改
3.2 日志技术体系结构![在这里插入图片描述](https://img-blog.csdnimg.cn/a89fadbc6d1947a984fcea83adea057b.png)
- 日志接口:设计日志框架的一套标准,日志框架需要实现这些接口。
- 注意1:
- 因为对Commons Logging接口不满意,有人就搞了SLF4
- 因为对Log4j的性能不满意,有人就搞了Logback
- 注意2:Logback是基于SLF4J的日志接口实现的框架,最常用
3.3 Logback日志框架
3.3.1 Logback概述
官方网站:Logback官方网站
Logback日志框架分为三个模块
- logback-core
- 基础模块,是其他两个模块依赖的基础(必须有)
- logback-classic
- 完整实现了SLF4J接口的模块(必须有)
- logback-access
- 与Tomcat和Jetty等Servlet容器集成,以提供HTTP访问日志的功能(可选)
想使用Logback日志框架,至少需要在项目中整合如下三个模块
- SLF4J-api:日志接口
- logback-core
- logback-classic
3.3.2 Logback快速入门
需求:使用Logback日志框架记录系统的运行信息,需要保存到文本中
实现步骤
-
导入Logback日志框架必备的三个模块到项目中
导入的三个jar包链接:https://pan.baidu.com/s/164Xz4tXpj4mA_xoS1pX4Ig?pwd=5r0r
提取码:5r0r
-
将Logback框架的核心配置文件logback.xml直接拷贝到src目录下(必须是src下)
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- CONSOLE :表示当前的日志信息是可以输出到控制台的。 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <!--输出流对象 默认 System.out 改为 System.err--> <target>System.out</target> <encoder> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %c [%thread] : %msg%n</pattern> </encoder> </appender> <!-- File是输出的方向通向文件的 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> <charset>utf-8</charset> </encoder> <!--日志输出路径--> <file> D:\code\黑马\code\properties-xml-log-app\src\log\data.log</file> <!--指定日志文件拆分和压缩规则--> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!--通过指定压缩文件名称,来确定分割文件方式--> <fileNamePattern>D:\development_tools\logback\log\log-%d{yyyy-MM-dd}.log%i.gz</fileNamePattern> <!--文件拆分大小--> <maxFileSize>1MB</maxFileSize> </rollingPolicy> </appender> <!-- level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR | ALL 和 OFF , 默认debug <root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。 --> <root level="ALL"> <!-- 注意:如果这里不配置关联打印位置,该位置将不会记录日志--> <appender-ref ref = "CONSOLE"/> <appender-ref ref="FILE" /> </root> </configuration>
-
创建Logback框架提供的Logger对象,然后用Logger对象调用其提供的方法就可以记录系统的日志信息
public static final Logger LOGGER = LoggerFactory.getLogger("类名");
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test2 {
// 获取日志记录器对象
// 传入的参数可以随意写,仅仅是为了区分不同的日志记录器对象,会在日志中展示
public static final Logger LOGGER = LoggerFactory.getLogger("Test2");
public static void main(String[] args) {
try {
//info级别的日志用于记录程序正常运行过程中的一些重要信息
//比如程序启动、关闭,用户登录、退出等
LOGGER.info("开始执行");
test(10,0);
LOGGER.info("执行结束");
} catch (Exception e) {
//error级别的日志用于记录程序运行过程中出现的异常信息
LOGGER.error("执行失败,出现了异常 ",e);
}
}
public static void test(int a,int b) {
//debug级别的日志用于记录程序运行过程中的一些细节信息,比如变量的值,方法的返回值等
LOGGER.debug("a = " + a);
LOGGER.debug("b = " + b);
int c = a / b;
LOGGER.info("c = " + c);
}
}
3.3.3 解读核心配置文件logback.xml
用于对Logback日志框架进行控制
(1)设置日志的输出位置
-
输出到控制台
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
-
输出到文件
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
(2)设置是否输出日志 (ALL开启日志,OFF关闭日志)
<!--开启日志-->
<root level="ALL">
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
<!--关闭日志-->
<root level="OFF">
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
3.3.4 logback.xml设置日志级别
日志级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下(优先级依次升高)
日志级别(由低到高) | 说明 |
---|---|
trace | 追踪,指明程序运行轨迹 |
debug | 调试,实际应用中一般将其作为最低级别,而trace则很少使用 |
info | 输出重要的运行信息,数据连接、网络连接、IO操作等等,使用较多 |
warn | 警告信息,可能会发生问题,使用较多 |
error | 错误信息,使用较多 |
作用:通过在xml中设置日志级别可以选择输出不同等级的日志信息
只有日志的级别是大于或等于核心配置文件配置的日志级别,才会被记录,否则不记录
<!--默认为debug,会输出debug、info、warn、error类型的日志-->
<root level="debug">
<!--如果只想输出到控制台或文件,选择删除下面中的某一句即可-->
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
<!--会输出info、warn、error类型的日志-->
<root level="info">
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
<!--会输出warn、error类型的日志-->
<root level="warn">
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
<!--只输出error类型的日志-->
<root level="error">
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
|
**作用**:通过在xml中设置日志级别可以选择输出不同等级的日志信息
**只有日志的级别是大于或等于核心配置文件配置的日志级别,才会被记录,否则不记录**
```xml
<!--默认为debug,会输出debug、info、warn、error类型的日志-->
<root level="debug">
<!--如果只想输出到控制台或文件,选择删除下面中的某一句即可-->
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
<!--会输出info、warn、error类型的日志-->
<root level="info">
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
<!--会输出warn、error类型的日志-->
<root level="warn">
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>
<!--只输出error类型的日志-->
<root level="error">
<appender-ref ref = "CONSOLE"/>
<appender-ref ref="FILE" />
</root>