java中的特殊文件和日志操作

java中的特殊文件和日志操作

1.0 Properties

该类用于对java中的特殊文件,即Properties文件进行操作,Properties文件是存储java中的一些本地键值对数

据的文件,该类继承自Map,但实际上并不去使用其继承自Map的方法,而是使用其封装后自己的方法。

下面是读取的一些方法

package SpecialFile;
import java.io.*;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class MyProperties {
    public static void main(String[] args) {
        try {
            Properties properties= new Properties();
            properties.load(new FileReader("src/SpecialFile/users.properties"));
            properties.forEach((k,v)-> System.out.println(k+"="+v));
            properties.get("name");//通过map的方法遍历
            properties.getProperty("name");//通过其自己的方法遍历
            Set<String> keys=properties.stringPropertyNames();//获取所有的键
            keys.forEach(key-> System.out.println(key+"="+properties.getProperty(key)));//输出
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

需要注意的是,使用properties在读取文件时,会采用默认的文件编码方式ISO-8859-1去处理读到的字节,所有无

法正确处理中文,如果想要正确处理中文,需要将ide中将文件编码方式改为utf-8 同时我们需要明白,存储在文件

中的数据是按utf-8等文件编码方式存储的,存储在内存中的内容是以unicode形式存储的,有这样一个转换过程。

下面是写入操作

package SpecialFile;
import java.io.*;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class MyProperties {
    public static void main(String[] args) {
        try {
            Properties properties= new Properties();
            properties.put("sex","man");//使用set的方法
            properties.setProperty("hobby","game");//使用其自己的方法
            properties.store(new FileWriter("src/SpecialFile/users.properties"),"个人信息");//封入低级管道然后写入
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

之前的put只是将数据存储在内存中,store方法则是将之前存储的数据一次性写入

如果我们要修改原来的值,可以用setProperty 方法

package SpecialFile;
import java.io.*;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class MyProperties {
    public static void main(String[] args) {
        try {
            Properties properties= new Properties();
            properties.load(new FileReader("src/SpecialFile/users.properties"));
            if(properties.getProperty("name")!=null){
                properties.setProperty("name","mr.wang");
            }
            else {
                properties.put("name", "mr.sun");
            }
            properties.store(new FileWriter("src/SpecialFile/users.properties"),"");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

1.1 XML文件

xml一般作为我们系统的配置文件,或者作为一种特殊的数据结构在网络上传播,不过当前一般使用json来传播数

据一般我们在xml中读取信息,需要注意,因为xml使用了一些字符去构成整个结构,所以当我们用到这些字符时为

了避免冲突应该使用xml给定的格式,下面是对应关系:

&lt    <
&gt    >
&amp   &
&apos  '
&quots "

但如果我们使用特殊数据区,则不会有这个问题

       <![CDATA[
                       
       ]]>

这是特殊数据区的格式

我们这里使用dom4j框架来解析xml,解析xml和我们javascript中解析html没有什么本质区别

<?xml version="1.0" encoding="UTF-8" ?>
<users>
    <user id="1" >
        <name>"bob"</name>
        <sex>man</sex>
        <age>15</age>
        <![CDATA[ ]]>
    </user>
    <contact>
    <http>https</http>
    </contact>
</users>

上面是我们测试用的xml文件

package SpecialFile;


import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.List;

public class Myxml {
    public static void main(String[] args) throws DocumentException {
        SAXReader reader =new SAXReader();//创建解析器对象
        Document doc =reader.read("src/SpecialFile/test.xml");
        Element rootElement = doc.getRootElement();//获得根元素
        System.out.println(rootElement.getName());
        List<Element> elements = rootElement.elements();//获取根元素下的每个子元素
        for (Element element : elements) {//对子元素进行遍历
            System.out.println(element.getName());
        }
        //我们也可也指定子元素;
        Element user = rootElement.element("user");//如果此时有多个同名的子元素,则会获得第一个
        System.out.println(user.elementText("name"));//获得当前元素的子元素对象中的文本值
        System.out.println(user.element("name").getText());//或者通过当前的子元素直接拿值
        System.out.println(user.element("name").getTextTrim());//加了trim时会去掉文本前后的空格
        Attribute userAttribute = user.attribute("id");//根据属性名字获得属性对象
        System.out.println(userAttribute.getName()+userAttribute.getValue());//获得属性的名称和值
        System.out.println(user.attributeValue("id"));//直接获得属性值


    }

}

上面该框架操作xml的一些常见操作

1.3 日志技术

我们记录日志时一般使用日志框架,为了统一,日志框架一般都需要遵循日志接口,日志分为JCL 这是java官方的

日志接口和 SLF4J 这是第三方的日志接口,这里介绍logbak日志框架,基于SLF4J日志接口

基于maven导入logback-classic 即可使用,其他的slf4j 的包和 logback-core都会作为其依赖进行导入

日志我们定义为一个静态常量

public static final Logger LOGGER =LoggerFactory.getLogger("LogBackTest");

传入的是该日志对象的标志,一般以类名作为标志,表明该日志常量定义的位置

对于关键日志,比如某行为的开始,使用关键日志:

LOGGER.info("start");

比如上面就是某行为的开始,结束同理

对于我们的调试行为,比如输出某值来查看,一般使用的是调试日志

LOGGER.debug("debug");

如果遇到了错误或者异常,被捕捉到,此时我们要使用的是错误日志

LOGGER.error("error:"+e.getMessage());

我们将其结合起来

package com.maven.logtest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class LogBackTest {
    public static final Logger LOGGER =LoggerFactory.getLogger("LogBackTest");
    public static void main(String[] args) {
        try {
            LOGGER.info("div start");
            div(1,2);
            LOGGER.info("div end");

        }
        catch (Exception e){
            LOGGER.error("error:"+e.getMessage());
        }

    }
    public static double div(double a,double b) throws Exception{
        double ans= a/b;
        LOGGER.debug("ans:"+ans);
        return ans;
    }
}

我们发现代码中似乎并没有控制日志信息的设置,那么日志信息是怎么被我们控制输出或者记录到文件中的呢?

这时候就需要用到位于resources文件夹下的logback.xml了,因为我们使用的是logback 所以虚拟机会根据该文件

的内容决定日志的处理

我当前使用的配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!--定义日志文件的存储地址 ,这个使用的是相对路径,即在日志文件存放在项目根路径logs文件夹下-->
    <property name="LOG_HOME" value="./logs/" />
    <!-- 控制台输出 -->
    <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.SizeAndTimeBasedRollingPolicy">
            <!-- 文件名模式,包含大小索引 -->
            <FileNamePattern>${LOG_HOME}/logs-study.log.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <!-- 单个文件最大大小 -->
            <maxFileSize>10MB</maxFileSize>
            <!-- 日志文件保留天数 -->
            <maxHistory>30</maxHistory>
            <!-- 所有日志文件总大小限制 -->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>


    <!-- 日志输出级别 ,一定要把上边定义的appender 写在下面否者会导致日志文件生成不了,或者为空的日志文件-->
    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </root>
</configuration>

其中我们设置了限制,每天会生成新的日志文件,并且单个日志文件超过10mb也会生成新的日志文件,如果总日

志文件大小超过1gb 就会删除到1gb

不过这个大小只记录日志信息,也就是我们在前面调用日志对象传入的信息,而不是实际输出的信息大小,即使我

们实际输出的日志信息远远大于我们传入的信息,也只是记录当我们传入的信息,当传入的信息达到大小上限时才

触发我们设定的操作

日志级别

日志级别是指日志信息的类型,分为

trace " 追踪程序的运行轨迹" 现在很少用,一般用debug

debug 调试程序的信息

info 输出重要的信息

warn 警告信息,可能会产生问题

error 错误信息,表明产生错误

上面的这几个日志级别从小到大排序

posted @ 2025-07-22 00:56  折翼的小鸟先生  阅读(3)  评论(0)    收藏  举报