十二、特殊文件和日志技术
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方法的效果) |
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); //rootSystem.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 ) | 把键值对数据,通过字符输出流写出到属性文件里去 |
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。
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 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解析库
下载链接:https://dom4j.github.io/
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() | 获取文本 |
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 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 的文件里。
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);}}
}