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. Python中如何生成requirements.txt文件

    Python项目中一般都包含一个名为 requirements.txt 文件,用来记录当前项目所有的依赖包和版本号,在一个新环境下通过该文件可以更方便的构建项目所需要的运行环境. 生成requirem ...

  2. php引入html文件(或php文件)的方法

    php引入html文件(或php文件)的方法 一.使用fopen()函数  此函数主要传入的是头两个参数(第一个是文件地址,第二个是打开方式),可以读取任何一个文本文件,然后用while将fopen函 ...

  3. Python脚本破解图形验证码(tesserocr和pytesseract)

    在学习之前,我们先了解OCR.tesseract.tesserocr.pytesseract和opencv这几个跟图片处理有关的库. OCR(Optical Character Recognition ...

  4. Matlab学生账号创建激活使用

    软件介绍 MATLAB主要用于数值分析.数值和符号计算.工程与科学绘图.控制系统的设计与仿真.数字图像处理.数字信号处理.通讯系统设计与仿真.财务与金融工程,是一款商业数学软件.MATLAB拥有丰富的 ...

  5. Instagram 为什么不用redis

    Hi 我还是大粽子 碎碎念 让我比较兴奋的就是这段时间的文章,被感兴趣的同学一一关注,关注量上涨就是我的最大动力. 我每周都会输出至少3篇原创文章,希望能被更多的同学关注,点赞,在看,形成习惯. In ...

  6. Excel-宏与VBA-数据类型

    学习视频,本文是观看前视频时做的笔记,手动感谢up. 数据类型 案例 声明一个变量并且赋值 Sub 变量() ' 声明一个变量用Dim,格式就是 Dim 变量名 As 数据类型 Dim Score A ...

  7. TLB和CPU缓存

    TLB 如果每次应用程序访问一个线性地址都需要先解析(查PDT,PTT)那么效率十分低,为了提高执行效率CPU在CPU内部建立了一个TLB表,此表和寄存器一样访问速度极高.其会记录线性地址和物理地址之 ...

  8. 项目展示$\beta$

    项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 要求 Beta阶段项目展示 我们在这个课程的目标是 提升团队管理及合作能力,开发一项满意的工程项目 这个作业在哪个具体方面帮助我们实现目 ...

  9. Beta_测试说明

    Beta阶段测试说明 测试发现的BUG Beta阶段测试BUG: 测试发现的BUG都放在BUG FIX里面 GitHUB issue BUG FIX 后端:实体识别结果重复. 解决:把处理结果的id和 ...

  10. [软件开发的目录规范、区分py文件的两种用途]

    [软件开发的目录规范] 软件开发的目录规范 bin: 执行文件 conf: 存放配置文件相关代码 core: 存放源文件,业务逻辑相关代码 db: 存放数据库文件,主要用于与数据库交互 lib: 存放 ...