12.特殊文件--黑马程序员

一、特殊文件

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中书写”<”、“&”等,可能会出现冲突,导致报错,此时可以用如下特殊字符替代
原符号替代符号
<(小于号)&lt;
>(大于号)&gt;
&(和)&amp;
'(单引号)&apos;
‘’(引号)&quot;
<?xml version="1.0" encoding="UTF-8" ?>
<users>
    <user id="1">
        <data1>
            3 &gt; 2 &amp; 1 &lt; 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包

  • 将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 &gt; 2 &amp; 1 &lt; 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 日志技术体系结构在这里插入图片描述

  • 日志接口:设计日志框架的一套标准,日志框架需要实现这些接口。
  • 注意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日志框架记录系统的运行信息,需要保存到文本中

实现步骤

  1. 导入Logback日志框架必备的三个模块到项目中

    导入的三个jar包链接:https://pan.baidu.com/s/164Xz4tXpj4mA_xoS1pX4Ig?pwd=5r0r

    提取码:5r0r

    在这里插入图片描述

  2. 将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>
    
  3. 创建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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值