目录
1.特殊文件和日志技术概述
1.1 特殊文件
特殊文件在 Java 中是实现数据持久化、共享、配置管理以及性能优化的重要工具

1.2 日志技术
把程序运行的信息,记录到文件中,方便程序员定位bug、并了解程序员的执行情况等
2.Properties
2.1读写Properties文件
package com.itheima.d1_properties;
import java.io.FileInputStream;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo1 {
public static void main(String[] args) throws Exception {
// 目标:Properties读取属性文件中的键值对数据.
// 1、创建属性集对象,代表一个属性文件
Properties properties = new Properties();
System.out.println(properties);
// 2、加载属性文件信息到属性集对象中去。
properties.load(new FileInputStream("day11-special-file-log-code\\src\\users.properties"));
System.out.println(properties);
// 根据键取值
// System.out.println(properties.get("赵敏"));
System.out.println(properties.getProperty("赵敏"));
//Map可以用keySet取出所有的键
//properties也可以用stringPropertyNames()取出所有的键
Set<String> keys = properties.stringPropertyNames();
for (String key : keys) {
String value = properties.getProperty(key);
System.out.println(key + "==>" + value);
}
// 3、遍历数据
properties.forEach((k, v) -> {
System.out.println(k + "===>" + v);
});
}
}
package com.itheima.d1_properties;
import java.io.FileWriter;
import java.util.Properties;
public class PropertiesDemo2 {
public static void main(String[] args) throws Exception {
// 目标:掌握使用Properties把键值对数据又写出去到属性文件中去。
// 1、创建属性集对象
Properties properties = new Properties();
//properties.put("admin", "66666");
properties.setProperty("admin", "66666");
properties.setProperty("玄冥二老", "wangfei");
properties.setProperty("金毛狮王", "成昆");
properties.setProperty("小昭", "wuji");
System.out.println(properties);
// 2、存储到文件
properties.store(new FileWriter("day11-special-file-log-code/src/users2.properties"),
"i saved many users! give me 100!");
}
}
2.2 案例
package com.itheima.d1_properties;
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 properties = new Properties();
// 2、加载属性文件中的键值对数据
//用字节输入流可能会乱码,尽量用字符输入流
properties.load(new FileReader("day11-special-file-log-code\\src\\people.txt"));
// 3、判断是否存在李芳,存在把其值改成18
if(properties.containsKey("李芳")){
properties.setProperty("李芳", "18");
}
// 4、把属性文件对象,重新存入到属性文件中去。
properties.store(new FileWriter("day11-special-file-log-code\\src\\people.txt"),
"give me 100 fen!");
}
}
3.XML文件
3.1 概述
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 以下是一个新的xml的内容 -->
<users>
<user id="1">
<name>张全蛋</name>
<sex>男</sex>
<age>32</age>
<hobby>炸机</hobby>
<sql>
select * from tb_student where age >= 18 && age <= 35
</sql>
</user>
<user id="2" desc="这是一个脱口秀演员">
<name>何广智</name>
<sex>男</sex>
<age>28</age>
<hobby>脱口秀</hobby>
<sql>
<![CDATA[
select * from tb_student where age >= 18 && age <= 35
]]>
</sql>
</user>
</users>
实际上目前在项目开发中我们用JSON格式存储数据的情况比较多,更简洁。
3.2 读取XML文件中的数据
我们可以用dom4j来解析XML
// 目标:解析XML文件:使用Dom4j框架。
// 1、创建一个SaxReader解析器对象
SAXReader saxReader = new SAXReader();
// 2、把xml文件读成一个Document文档对象。
Document document =
saxReader.read("day11-special-file-log-code\\src\\Contact.xml");
// 3、文档对象中包含了XML的全部数据,提供了方法获取数据
Element rootElement = document.getRootElement();
System.out.println(rootElement.getName());
目前能 rootElement.getName() 能得到的就是xml文件中的根元素,如:<users>
下面我们可以用Element提供的方法来提取子元素
package com.itheima.d2_xml;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.util.List;
public class Dom4JTest1 {
public static void main(String[] args) throws Exception {
// 目标:解析XML文件:使用Dom4j框架。
// 1、创建一个SaxReader解析器对象
SAXReader saxReader = new SAXReader();
// 2、把xml文件读成一个Document文档对象。
Document document =
saxReader.read("day11-special-file-log-code\\src\\Contact.xml");
// 3、文档对象中包含了XML的全部数据,提供了方法获取数据
Element rootElement = document.getRootElement();
System.out.println(rootElement.getName());
// 4、提取子元素对象
//提取所有的子元素对象
//List<Element> sonEles = rootElement.elements();
//只要contact
List<Element> sonEles = rootElement.elements("contact");
for (Element sonEle : sonEles) {
System.out.println(sonEle.getName());
}
System.out.println("---------------------------------------");
// 指定获取单个子元素对象,父元素拿子元素只能拿一级子元素
Element userEle = rootElement.element("user");
System.out.println(userEle.elementText("name"));//提取到name的值
System.out.println("---------------------------------------");
Element contactEle = rootElement.element("contact"); // 默认拿第一个contact!
System.out.println(contactEle.elementText("name"));//拿到只第一个contact的子元素name中的数据
// 5、提取子元素的属性对象。
//contactEle在前面默认拿到的是第一个contact
Attribute idAttr = contactEle.attribute("id");
System.out.println(idAttr.getName());//id
System.out.println(idAttr.getValue());//1
// 直接拿属性值,比上面的方法更简洁
System.out.println(contactEle.attributeValue("id"));//直接拿到 1
// 6、文本值
// 通过父元素拿到子元素文本值
System.out.println(contactEle.elementText("name"));
System.out.println(contactEle.elementTextTrim("name")); // 去掉前后空格输出值
// 先拿到元素对象,再提取其文本值
Element emailEle = contactEle.element("email");
System.out.println(emailEle.getText());
System.out.println(emailEle.getTextTrim()); // 去掉前后空格
}
}
dom4j解析案例
package com.itheima.d2_xml;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.util.ArrayList;
import java.util.List;
public class Dom4JTest2 {
public static void main(String[] args) throws Exception {
// 目标:解析XML文件:使用Dom4j框架。
// 1、创建一个SaxReader解析器对象
SAXReader saxReader = new SAXReader();
// 2、把xml文件读成一个Document文档对象。
Document document =
saxReader.read("day11-special-file-log-code\\src\\Contact.xml");
// 3、文档对象中包含了XML的全部数据,提供了方法获取数据
Element rootElement = document.getRootElement();
// 4、准备一个联系人集合存储联系人对象
List<Contact> contacts = new ArrayList<>();
// 5、提取全部一级联系人元素对象
List<Element> sonEles = rootElement.elements("contact");
// 6、遍历子元素对象
for (Element sonEle : sonEles) {
// 7、每个子元素是一个联系人对象,创建联系人对象,封装数据
Contact contact = new Contact();
// 注入数据。
contact.setId(Integer.valueOf(sonEle.attributeValue("id")));
contact.setName(sonEle.elementTextTrim("name"));
contact.setGender(sonEle.elementTextTrim("gender").charAt(0));
contact.setEmail(sonEle.elementTextTrim("email"));
// 8、存入到集合中去
contacts.add(contact);
}
System.out.println(contacts);
}
}
注意从xml文件中获取到值以后为对象赋值时注意数据类型转换
3.3 XML的创建
那么我们如何使用程序把数据写出到XML文件中去?不建议用dom4j做
推荐直接把程序里的数据拼接成XML格式,然后用IO流写出去!
package com.itheima.d2_xml;
import java.io.PrintStream;
public class Dom4JTest3 {
public static void main(String[] args) throws Exception {
// 目标:写一个xml的数据出去
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
sb.append("<user>\r\n");
sb.append("\t<name>").append("张三").append("</name>\r\n");
sb.append("\t<age>").append("12").append("</age>\r\n");
sb.append("\t<sex>").append("男").append("</sex>\r\n");
sb.append("</user>\r\n");
PrintStream ps = new PrintStream("day11-special-file-log-code/src/users3.xml");
ps.println(sb);
ps.close();
}
}
3.4 补充:约束XML文件的编写
3.4.1 XML文档约束-DTD的使用(了解)
DTD也有局限性:它可以约束XML文件的编写,但是不能约束具体的数据类型
3.4.2 XML文档约束-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>
4.日志技术
- 可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。
- 可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改
4.1 日志技术的体系结构
4.2 Logback日志技术快速入门
package com.itheima.d3_logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test {
// 1、创建一个Logback框架的Logger日志对象,来记日志。
public static final Logger LOGGER = LoggerFactory.getLogger("Test.class");
public static void main(String[] args) {
try {
LOGGER.info("除法开始了。。。。。");
chu(10, 0);
LOGGER.info("除法执行成功了。。。。。");
} catch (Exception e) {
LOGGER.error("除法执行失败了:" + e.getMessage());
}
}
public static void chu(int a, int b) {
LOGGER.debug("参数a:" + a);
LOGGER.debug("参数b:" + b);
int c = a / b;
LOGGER.info("结果c是:" + c);
}
}
在控制台和log文件中都会记录日志

4.3 日志技术的核心配置文件
这个核心配置文件logback.xml 一定要配置在src下,他是整个logback日志框架的闸口,当我们在用这个logback框架记日志时,所有的日志对象都会通过这个核心配置文件来进行整个项目的管控
<?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:/log/itheima-data.log</file>
<!--指定日志文件拆分和压缩规则-->
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--通过指定压缩文件名称,来确定分割文件方式-->
<fileNamePattern>D:/log/itheima-data-%i-%d{yyyy-MM-dd}-.log.gz</fileNamePattern>
<!--文件拆分大小-->
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
</appender>
<!--
1、控制日志的输出情况:如,开启日志,取消日志
all 代表打印全部日志
off 关闭全部日志
debug info error
-->
<root level="all">
<!-- 在控制台打印日志-->
<appender-ref ref="CONSOLE"/>
<!-- 在文件中打印日志-->
<appender-ref ref="FILE" />
</root>
</configuration>
4.4 日志级别
核心配置文件配置的日志级别在以下代码中:
<root level="all">
<!-- 在控制台打印日志-->
<appender-ref ref="CONSOLE"/>
<!-- 在文件中打印日志-->
<appender-ref ref="FILE" />
</root>
只会打印大于或等于level的日志级别,也可以不写,不写的话就会默认配置debug级别。