properties使用

什么是Properties?

Properties(Java.util.Properties),该类主要用于读取Java的配置文件,不同的编程语言有自己所支持的配置文件,配置文件中很多变量是经常改变的,为了方便用户的配置,能让用户够脱离程序本身去修改相关的变量设置。就像在Java中,其配置文件常为.properties文件,是以键值对的形式进行参数配置的。

Properties 详解

properties结构

Api介绍

  • 构造函数

构造函数 说明
Properties() 创建空的Properties
Properties(Properties ps) 基于已经存在的properties去创建
  • 常用方法

方法 说明
public synchronized void load(InputStream inStream) 给予输入流去加载Properties
public synchronized void load(Reader reader) 给予文本输入流去加载Properties
Object setProperty(String key, String value) 设置属性
public synchronized void load(InputStream inStream) 给予输入流去加载Properties
public void store(Writer writer, String comments) 保存文件
public String getProperty(String key) 获取properties key
  • 源码讲解

load源码分析

指定从流中加载key/value属性值,底层都是将流封装成为LineReader对象,然后通过load0方法来加载属性键值对的,加载完属性后流对象是不会关闭的。这两个方法对应的properties文件格式如下:

 class LineReader {
        /**
         * 根据字节流创建LineReader对象
         * 
         * @param inStream
         *            属性键值对对应的字节流对象
         */
        public LineReader(InputStream inStream) {
            this.inStream = inStream;
            inByteBuf = new byte[8192];
        }

        /**
         * 根据字符流创建LineReader对象
         * 
         * @param reader
         *            属性键值对对应的字符流对象
         */
        public LineReader(Reader reader) {
            this.reader = reader;
            inCharBuf = new char[8192];
        }

        // 字节流缓冲区, 大小为8192个字节
        byte[] inByteBuf;
        // 字符流缓冲区,大小为8192个字符
        char[] inCharBuf;
        // 当前行信息的缓冲区,大小为1024个字符
        char[] lineBuf = new char[1024];
        // 读取一行数据时候的实际读取大小
        int inLimit = 0;
        // 读取的时候指向当前字符位置
        int inOff = 0;
        // 字节流对象
        InputStream inStream;
        // 字符流对象
        Reader reader;

        /**
         * 读取一行,将行信息保存到{@link lineBuf}对象中,并返回实际的字符个数
         * 
         * @return 实际读取的字符个数
         * @throws IOException
         */
        int readLine() throws IOException {
            // 总的字符长度
            int len = 0;
            // 当前字符
            char c = 0;

            boolean skipWhiteSpace = true;
            boolean isCommentLine = false;
            boolean isNewLine = true;
            boolean appendedLineBegin = false;
            boolean precedingBackslash = false;
            boolean skipLF = false;

            while (true) {
                if (inOff >= inLimit) {
                    // 读取一行数据,并返回这一行的实际读取大小
                    inLimit = (inStream == null) ? reader.read(inCharBuf) : inStream.read(inByteBuf);
                    inOff = 0;
                    // 如果没有读取到数据,那么就直接结束读取操作
                    if (inLimit <= 0) {
                        // 如果当前长度为0或者是改行是注释,那么就返回-1。否则返回len的值。
                        if (len == 0 || isCommentLine) {
                            return -1;
                        }
                        return len;
                    }
                }

                // 判断是根据字符流还是字节流读取当前字符
                if (inStream != null) {
                    // The line below is equivalent to calling a ISO8859-1 decoder.
                    // 字节流是根据ISO8859-1进行编码的,所以在这里进行解码操作。
                    c = (char) (0xff & inByteBuf[inOff++]);
                } else {
                    c = inCharBuf[inOff++];
                }

                // 如果前一个字符是换行符号,那么判断当前字符是否也是换行符号
                if (skipLF) {
                    skipLF = false;
                    if (c == '\n') {
                        continue;
                    }
                }

                // 如果前一个字符是空格,那么判断当前字符是不是空格类字符
                if (skipWhiteSpace) {
                    if (c == ' ' || c == '\t' || c == '\f') {
                        continue;
                    }
                    if (!appendedLineBegin && (c == '\r' || c == '\n')) {
                        continue;
                    }
                    skipWhiteSpace = false;
                    appendedLineBegin = false;
                }

                // 如果当前新的一行,那么进入该if判断中
                if (isNewLine) {
                    isNewLine = false;
                    // 如果当前字符是#或者是!,那么表示该行是一个注释行
                    if (c == '#' || c == '!') {
                        isCommentLine = true;
                        continue;
                    }
                }

                // 根据当前字符是不是换行符号进行判断操作
                if (c != '\n' && c != '\r') {
                    // 当前字符不是换行符号
                    lineBuf[len++] = c;// 将当前字符写入到行信息缓冲区中,并将len自增加1.
                    // 如果len的长度大于行信息缓冲区的大小,那么对lineBuf进行扩容,扩容大小为原来的两倍,最大为Integer.MAX_VALUE
                    if (len == lineBuf.length) {
                        int newLength = lineBuf.length * 2;
                        if (newLength < 0) {
                            newLength = Integer.MAX_VALUE;
                        }
                        char[] buf = new char[newLength];
                        System.arraycopy(lineBuf, 0, buf, 0, lineBuf.length);
                        lineBuf = buf;
                    }
                    // 是否是转义字符
                    // flip the preceding backslash flag
                    if (c == '\\') {
                        precedingBackslash = !precedingBackslash;
                    } else {
                        precedingBackslash = false;
                    }
                } else {
                    // reached EOL
                    if (isCommentLine || len == 0) {
                        // 如果这一行是注释行,或者是当前长度为0,那么进行clean操作。
                        isCommentLine = false;
                        isNewLine = true;
                        skipWhiteSpace = true;
                        len = 0;
                        continue;
                    }
                    // 如果已经没有数据了,就重新读取
                    if (inOff >= inLimit) {
                        inLimit = (inStream == null) ? reader.read(inCharBuf) : inStream.read(inByteBuf);
                        inOff = 0;
                        if (inLimit <= 0) {
                            return len;
                        }
                    }
                    // 查看是否是转义字符
                    if (precedingBackslash) {
                        // 如果是,那么表示是另起一行,进行属性的定义,len要自减少1.
                        len -= 1;
                        // skip the leading whitespace characters in following line
                        skipWhiteSpace = true;
                        appendedLineBegin = true;
                        precedingBackslash = false;
                        if (c == '\r') {
                            skipLF = true;
                        }
                    } else {
                        return len;
                    }
                }

            }
        }
    }

store源码分析

private void store0(BufferedWriter bw, String comments, boolean escUnicode) throws IOException {
 2         if (comments != null) {
 3             // 写出注释, 如果是中文注释,那么转化成为8859-1的字符
 4             writeComments(bw, comments);
 5         }
 6         // 写出时间注释
 7         bw.write("#" + new Date().toString());
 8         // 新起一行
 9         bw.newLine();
10         // 进行线程间同步的并发控制
11         synchronized (this) {
12             for (Enumeration e = keys(); e.hasMoreElements();) {
13                 String key = (String) e.nextElement();
14                 String val = (String) get(key);
15                 // 针对空格进行转义,并根据是否需要进行8859-1编码
16                 key = saveConvert(key, true, escUnicode);
17                 /*
18                  * No need to escape embedded and trailing spaces for value,
19                  * hence pass false to flag.
20                  */
21                 // value不对空格进行转义
22                 val = saveConvert(val, false, escUnicode);
23                 // 写出key/value键值对
24                 bw.write(key + "=" + val);
25                 bw.newLine();
26             }
27         }
28         bw.flush();
29     }

properties实战

实现读取ex1.properties文件写入另外一个文件ex2.properties

  • 准备文件test.properties
#bbaba
#Mon Jun 07 11:38:21 CST 2021
hah=ceshi
  • 开始拷贝
Properties properties = new Properties();
properties.load(new FileReader(new File("test.properties")));
System.out.println(properties.get("hah"));
properties.store(new FileWriter(new File("test2.properties")),"ceshi2");
  • 控制台输出
ceshi
Process finished with exit code 0

此时classpath下可以查看到新建的test2.properties文件。

结束

识别下方二维码!回复: 入群 ,扫码加入我们交流群!

点赞是认可,在看是支持

java IO教程《四》的更多相关文章

  1. Java IO教程

    1  Java IO 教程 2 Java IO 概述 3 Java IO: 文件 4 Java IO: 管道 5 Java IO: 网络 6 Java IO: 字节和字符数组 7 Java IO: S ...

  2. Java IO(四) InputStream 和 OutputStream

    Java IO(四) InputStream 和 OutputStream 一.介绍 InputStream 和 OutputStream 是字节流的超类(父类),都是抽象类,都是通过实例化它们的子类 ...

  3. Java IO学习--(四)网络

    Java中网络的内容或多或少的超出了Java IO的范畴.关于Java网络更多的是在我的Java网络教程中探讨.但是既然网络是一个常见的数据来源以及数据流目的地,并且因为你使用Java IO的API通 ...

  4. Java IO(四)——字符流

    一.字符流 字节流提供了处理任何类型输入/输出操作的功能(因为对于计算机而言,一切都是0和1,只需把数据以字节形式表示就够了),但它们不可以直接操作Unicode字符,因为一个Unicode字符占用2 ...

  5. Java IO教程 导读

    Java IO是一套java 用来读写数据(输入和输出)的API.大部分程序都要处理一些输入,并有输入产生一些输出.Java为此提供了java.io包. 如果你浏览下java.io包,会对其中各样的类 ...

  6. Java IO(四)

    在文件操作流中,输入输出的目标都是文件,但是有时候,我们并不需要写入文件,只是需要中转一下而已,这样就会显得很麻烦,所以我们就可以使用内存操作流.在内存操作流中,输入输出目标都是内存. 内存输出流:B ...

  7. 系统学习 Java IO (十四)----字符读写缓存和回退 BufferedReader/BufferedWriter & PushbackReader

    目录:系统学习 Java IO---- 目录,概览 BufferedReader BufferedReader 类构造器接收一个 Reader 对象,为 Reader 实例提供缓冲. 缓冲可以加快 I ...

  8. java IO教程《三》

    缓冲区流讲解(Buffered) 什么是缓冲区? 缓冲流,也叫高效流,是对4个基本的File流的增强,所以也是4个流,按照数据类型分类: 字节缓冲流:BufferedInputStream,Buffe ...

  9. Java入门教程四(字符串处理)

    Java 语言的文本数据被保存为字符或字符串类型.字符及字符串的操作主要用到 String 类和 StringBuffer 类,如连接.修改.替换.比较和查找等. 定义字符串 直接定义字符串 直接定义 ...

随机推荐

  1. 2021S软件工程——案例分析作业

    2021S软件工程--案例分析作业 18231169 黄思为 项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任建) 这个作业的要求在哪里 案例分析作业 我在这个课程的目标是 了解并熟悉 ...

  2. 【Spring】 Spring如何解决循环依赖的问题?

    https://mp.weixin.qq.com/s/FtbzTMxHgzL0G1R2pSlh-A 通常来说,如果问Spring内部如何解决循环依赖,一定是单默认的单例Bean中,属性互相引用的场景. ...

  3. hdu3870 基于最短路的最小割

    题意:      给你一个平面图,让你输出(1,1),(n ,n)的最小割.. 思路:       看完题想都没想直接最大流,结果TLE,想想也是 G<400*400,400*400*4> ...

  4. 0901-生成对抗网络GAN的原理简介

    0901-生成对抗网络GAN的原理简介 目录 一.GAN 概述 二.GAN 的网络结构 三.通过一个举例具体化 GAN 四.GAN 的设计细节 pytorch完整教程目录:https://www.cn ...

  5. JavaScript 包管理器 -Yarn

    Fast, reliable, and secure dependency management. 官网地址 Github 特性 离线模式:如果您之前下载了软件包,则可以在没有任何互联网连接的情况下安 ...

  6. python-内置函数-callable,chr,ord,bytes,随机验证码生成

    s="老男人" bytes(s,encoding="utf-8") 随机验证码的实现方法: 大写字母: li = [] for i in range(6): t ...

  7. Java 进行时间处理

    Java 进行时间处理 一.Calendar (1).Calender介绍 Calendar的中文翻译是日历,实际上,在历史上有着许多种计时的方法.所以为了计时的统一,必需指定一个日历的选择.那现在最 ...

  8. 推荐几款MySQL相关工具

    前言: 随着互联网技术的不断发展, MySQL 相关生态也越来越完善,越来越多的工具涌现出来.一些公司或个人纷纷开源出一些不错的工具,本篇文章主要介绍几款 MySQL 相关实用工具.提醒下,这里并不介 ...

  9. lower_bound和upper_bound的实现

    int lowerBound(int* nums, int numsSize, int target) { //注意left和right的初始值必须是left = 0, right = numsSzi ...

  10. 都 2021 年了,竟然有人搞大数据时忽略 JSON 而去研究用 C# 把 XML 转换为 XML 的技术

    在大数据项目开发过程中,ETL(Extract-Transform-Load)是必不可少.即便目前 JSON 非常流行,开发人员也有必定会有对远古系统的挑战,而 XML 格式的数据源作为经典存在浑身上 ...