十二、特殊文件和日志技术
1、特殊文件
properties:用来存储键值对数据。
xml:用来存储有关系的数据。
1.1 properties文件
特点:存储键值对,键不能重复,文件后缀一般是.properties结尾的。
properties:是一个Map集合,但是一般不能用来当集合使用。
核心作用: Properties是用来代表属性文件的,通过Properties 可以读写属性文件里的内容。
构造器 | 说明 |
---|---|
public Properties() | 用于构建Properties集合对象(空容器) |
使用Properties读取键值对数据常用方法 | 说明 |
---|---|
public void load( InputStream is ) | 通过字节输入流,读取属性文件里的键值对数据 |
public void load( Reader reader ) | 通过字符输入流,读取属性文件里的键值对数据 |
public String getProperty( String key ) | 根据键获取值(其实就是get方法的效果) |
public Set stringPropertyNames() | 获取全部键的集合(其实就是ketSet方法的效果) |
java
public class PropertiesTest {
public static void main(String[] args) throws Exception {
Properties properties=new Properties();
properties.load(new FileReader("object-app\\src\\akc4\\SpecialFile\\abc.properties"));
//根据健来获取值
System.out.println(properties); //{password=123, name=root}
String name=properties.getProperty("name");
String password=properties.getProperty("password");
System.out.println(name); //root
System.out.println(password); //123
//获取全部键存到set集合里面去
Set<String> keys= properties.stringPropertyNames();
//遍历所有内容
for (String key:keys) {
String value=properties.getProperty(key);
System.out.println(key+"----->"+value);
// password----->123
//name----->root
}
}
}
使用Properties写入键值对数据常用方法 | 说明 |
---|---|
public Object setProperty(String key , String value) | 保存键值对数据到Properties对象中去。 |
public void store(OutputStream os , String comments ) | 把键值对数据,通过字节输出流写出到属性文件里去 |
public void store( Writer w ,String comments ) | 把键值对数据,通过字符输出流写出到属性文件里去 |
java
public class PropertiesTest {
public static void main(String[] args) throws Exception {
Properties properties=new Properties();
//将键值对数据先保存到properties对象中去
properties.setProperty("小明","54321");
properties.setProperty("小花","1234");
properties.setProperty("红红","5555");
System.out.println(properties);
//将对象数据保存到properties文件中去,如果没有该文件会自动创建。参数:(字节或字符输出流,注释)
properties.store(new FileWriter("object-app\\src\\akc4\\SpecialFile\\123.properties"),"用户名和密码");
}
}
1.1.2 例题
有一个info.txt文件,里面包含键值对:小明=12,小花=18,小罗=19,小天=20,判断里面是否有小罗,如果有,将值改为18。
java
public class PropertiesTest {
public static void main(String[] args) throws Exception {
//创建一个properties对象
Properties properties=new Properties();
//将文件加载到项目中来
properties.load(new FileReader("object-app\\src\\akc4\\SpecialFile\\info.txt"));
//因为Properties是Map中的集合,所有可通过Map提供的方法containKey方法来进行判断健是否存在。
if (properties.containsKey("小罗")){
//存在,将properties对象中,小罗的值进行替换
properties.setProperty("小罗","18");
//将对象的新值写入到对应文件中去
properties.store(new FileWriter("object-app\\src\\akc4\\SpecialFile\\info.txt"),"姓名和年龄");
System.out.println("修改成功!");
}else{
System.out.println("小罗不存在!");
}
}
}
1.2 XML 可扩展标记语言
作用:本质是一种数据格式,可以存储复杂的数据结构,和数据关系。
应用场景:经常用来做为系统的配置文件;或者作为-种特殊的数据结构,在网络中进行传输。格式如下:
xml
<!--开头必须是固定的格式-->
<?xml version="1.0" encoding="UTF-8" ?>
<!--只有一个根标签-->
<users>
<user id="1">
<name>小明</name>
<sex>男</sex>
<地址>四川</地址>
</user>
<user id="2">
<name>小花</name>
<sex>女</sex>
<地址>四川</地址>
</user>
</users>
在XML中,需要转义的字符有:
& &
< <
> >
" "
' '
也可以输入CD,再回车,就会出现 <![CDATA[ ]]>,在中括号里就可以输入任意字符了。
1.2.1 DOM4J解析库
DOM4J解析XML-得到Document对象
SAXReader: Dom4j提供的解析器,可以认为是代表整个Dom4j框架
构造器/方法 | 说明 |
---|---|
public SAXReader() | 构建DOM4J的解析器对象 |
public Document read(String url ) | 把XML文件读成Document对象 |
public Document read(InputStream is) | 通过字节输入流读取XML文件 |
方法名 | 说明 |
---|---|
Element getRootElement() | 获得根元素对象 |
通过根元素能调用的元素方法获取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() | 获取文本 |
java
public class Dom4jInputTest {
public static void main(String[] args) throws Exception {
//创建一个saxReader对象
SAXReader saxReader=new SAXReader();
//将xml文件读成Document对象
Document document= saxReader.read("object-app\\src\\akc4\\xmlDir\\info.xml");
//通过Document对象调用方法读取根以元素
Element rootElement=document.getRootElement();
//获取元素名
System.out.println(rootElement.getName());//users
//获取根元素下第一个元素为user的元素,再获取元素对应的id属性值
String id1=rootElement.element("user").attributeValue("id");
System.out.println(id1); //1
//获取根元素下第一元素为user的元素,再向下的name元素,获取其对应的文本
String name=rootElement.element("user").element("name").getText();
System.out.println(name); //小明
//获取根元素下的所有元素存放到list集合中
List<Element> listElements=rootElement.elements();
//遍历xml中所有人的个人信息
for (Element listElemnt: listElements) {
System.out.println("----------------------------");
System.out.println(listElemnt.element("name").getText());
System.out.println(listElemnt.element("sex").getText());
System.out.println(listElemnt.element("地址").getText());
}
}
}
写出XML数据:推荐直接把程序里的数据拼接成XML格式,然后用IO流写出去!
1、通过StringBuilder来进行拼接xml。
2、将拼接好的字符串通过缓冲字符输出流输出到xml文件中就行。
2、日志技术
作用1:把程序运行的信息,记录到文件中,方便程序员定位bug、并了解程序的执行情况等。
作用2:可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改。
因为对Commons Logging接口不满意,有人就搞了SLF4};因为对Log4j的性能不满意,有人就搞了Logback。
下载对应的jar包: slf4j-api
、``logback-core、
logback-classic`
下载jar包网站,以后所以的jar包都可以在里面下载,也支持maven下载。
网站链接:https://mvnrepository.com
注意版本间是兼容,可参考:slf4j-api-1.7.26、logback-core-1.2.3、logback-classic-1.2.3
2.1 实现步骤
-
导入
slf4j-api
、logback-core
、logback-classic
框架到项目中去。 -
将Logback框架的核心配置文件logback.xml直接拷贝到src目录下(必须是src下),logback.xml如下:注意改一下路径,改到自己的项目目录下的某个地方。
value="W:/StudyFile.."
xml<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> <property name="LOG_HOME" value="W:/StudyFile/Java/Projiect/BasicTraining/object-app/src/log"/> <!--日志输出位置:控制台日志, 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!--文件日志, 按照每天生成日志文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日志文件输出的文件名--> <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern> <!--日志文件保留天数--> <MaxHistory>30</MaxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <!--日志输出编码--> <charset>UTF-8</charset> </encoder> <!--日志文件最大的大小--> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> <!-- show parameters for hibernate sql 专为 Hibernate 定制 --> <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" /> <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" /> <logger name="org.hibernate.SQL" level="DEBUG" /> <logger name="org.hibernate.engine.QueryParameters" level="DEBUG" /> <logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" /> <!--myibatis log configure--> <logger name="com.apache.ibatis" level="TRACE"/> <logger name="java.sql.Connection" level="DEBUG"/> <logger name="java.sql.Statement" level="DEBUG"/> <logger name="java.sql.PreparedStatement" level="DEBUG"/> <!-- 日志输出级别 (level="OFF" 所有是日志都不记录,level="ALL" 所有的日志都被记录,level="DEBUG" 代表所有等级为DEBUG及以上的日志(即 DEBUG, INFO, WARN, ERROR)都会被记录下来。) --> <root level="DEBUG"> <!--输出到控制台--> <appender-ref ref="STDOUT" /> <!--输出到文件--> <appender-ref ref="FILE"/> </root> </configuration>
日志级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下表(优先级依次升高) :
只有日志的级别是大于或等于核心配置文件配置的日志级别,才会被记录,否则不记录。
日志级别 说明 trace 追踪,指明程序运行轨迹 debug 调试,实际应用中一般将其作为最低级别,而trace则很少使用 info 输出重要的运行信息,数据连接、网络连接、10操作等等,使用较多 warn 警告信息, 可能会发生问题,使用较多 error 错误信息,使用较多 -
创建Logback框架提供的Logger对象,然后用Logger对象调用其提供的方法就可以记录系统的日志信息。类名随便取。
public static final Logger LOGGER = LoggerFactory. getLogger("类名");
2.2 测试代码
会在控制台上输出,也会写入到 :TestWeb+文件修改日期.log 的文件里。
java
public class LogBackTest {
//创建一个日志对象
public static final Logger LOGGER= LoggerFactory.getLogger("LogTest");
public static void main(String[] args) {
LOGGER.info("开始记录日志!");
chu(10,0);
LOGGER.info("执行成功日志!");
}
public static void chu(int a,int b){
LOGGER.debug("传入的值为:a="+a+",b="+b);
try {
int c=a/b;
LOGGER.info("结果为:"+c);
}catch(Exception e){
LOGGER.error("错误日志:"+e);
}
}
}