likes
comments
collection
share

面对Properties的各种坑,你需要知道的Java小技巧

作者站长头像
站长
· 阅读数 32

面对Properties的各种坑,你需要知道的Java小技巧

  咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~

面对Properties的各种坑,你需要知道的Java小技巧


🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

  在Java日常开发中,Properties是一种常用的键值对存储方式,用于配置文件和环境变量等常见场景。但是,在使用Properties时,经常会遇到各种坑,例如读写乱码、键值对中含有特殊字符等问题。本文将通过代码示例和场景案例,介绍如何避免这些问题,让你在使用Properties时更加得心应手。

摘要

  • Properties是Java中常用的键值对存储方式,用于配置文件和环境变量等场景。
  • 在使用Properties时,需要注意读写乱码、键值对中特殊字符的处理等问题。
  • 通过代码示例和场景案例,本文介绍了如何避免这些问题,让你在使用Properties时更加得心应手。

Properties讲解

简介

  Properties是Java中常用的键值对存储方式,其存储方式和Map类似。Properties可以通过load()方法从文件中读取内容,也可以直接通过setProperty()方法添加键值对。Properties一般用于存储配置文件和环境变量等常见场景,其优点在于格式简单、易于阅读和修改。

下面是一个简单的Properties示例:

#配置文件示例
ip=192.168.1.1
port=8080
username=admin
password=123456

读取配置文件内容的代码如下:

Properties props = new Properties();
InputStream in = new BufferedInputStream(new FileInputStream("config.properties"));
props.load(in);
in.close();

String ip = props.getProperty("ip");
int port = Integer.parseInt(props.getProperty("port"));
String username = props.getProperty("username");
String password = props.getProperty("password");

源代码解析

读取Properties乱码问题

在读取Properties文件时,有可能出现乱码问题。这是因为Properties默认使用ISO-8859-1编码方式,如果我们的文件是其他编码方式,就会出现乱码。

面对Properties的各种坑,你需要知道的Java小技巧

解决方法如下:

Properties props = new Properties();
InputStream in = new FileInputStream("config.properties");
props.load(new InputStreamReader(in, "UTF-8"));
in.close();

String ip = props.getProperty("ip");
int port = Integer.parseInt(props.getProperty("port"));
String username = props.getProperty("username");
String password = props.getProperty("password");

  在读取Properties文件时,使用InputStreamReader指定文件的编码方式为UTF-8即可。

拓展:

  上述代码使用了 Java 中的 Properties类来读取一个名为 "config.properties" 的文件。该文件中包含了用于连接远程服务器的 IP 地址,端口,用户名和密码等信息。

  首先创建一个 Properties对象,并加载 config.properties 文件。通过 FileInputStream 类和 InputStreamReader 类来读取该文件,并且使用 UTF-8 编码解析文件内容。最后关闭输入流。

  然后,从读取的 Properties 对象中获取 IP 地址、端口、用户名和密码等属性值,并将它们分别存储在字符串和整数类型的变量中。

  通过这种方式,就可以方便地读取并使用 config.properties 文件中的配置信息。

Properties中键值对含有特殊字符

  当键值对中含有特殊字符时,例如空格、冒号等,需要进行特殊处理。

下面是两种方法:

Properties props = new Properties();
InputStream in = new FileInputStream("config.properties");
props.load(in);
in.close();

String ip = props.getProperty("ip");
String port = props.getProperty("port");
String username = props.getProperty("username");
String password = props.getProperty("password");

//方法一
ip = ip.replaceAll("\\s+", "");
port = port.replaceAll(":","");
username = username.replaceAll("\"","");
password = password.replaceAll("\'","");

//方法二
ip = ip.replace(" ", "");
port = port.replace(":", "");
username = username.replace("\"", "");
password = password.replace("\'", "");

  方法一使用正则表达式replaceAll()方法,将特殊字符替换为空字符串;方法二使用replace()方法,将特殊字符替换为普通字符。

拓展:

  该代码是读取一个配置文件(config.properties),并且获取其中的IP地址、端口号、用户名和密码。然后使用两种方法将获取的值进行处理。

  方法一使用了正则表达式,将IP地址中的空格、端口号中的冒号以及用户名和密码中的引号删除。

  方法二则直接使用了字符串的replace()方法,将空格、冒号和引号替换为""(空字符串)。

  这些处理的目的都是为了获得一个干净、规范的字符串,以便后续的操作。

写入Properties文件

写入Properties文件有两种方法,一种是使用OutputStream写入,另一种是使用Properties.store()方法写入。

//方法一
OutputStream out = new FileOutputStream("config.properties");
props.store(out, "update");
out.close();

//方法二
FileOutputStream output = new FileOutputStream("config.properties");
props.store(new OutputStreamWriter(output, "utf-8"), "update");
output.close();

  在写入Properties文件时,需要注意文件的编码方式,一般使用UTF-8。

拓展:

  以上代码是在Java中操作properties文件的示例代码,其中props代表一个Properties对象,它包含了一些配置信息。在这段代码中,通过将Properties对象写入OutputStream或OutputStreamWriter,将其保存到config.properties文件中。

  方法一使用了FileOutputStream,直接将Properties对象写入输出流中,使用store()方法进行保存。该方法使用了默认的ISO-8859-1编码格式,因此如果文件中含有中文等特殊字符可能会出现乱码。最后使用close()方法关闭输出流。

  方法二使用了更加灵活的方式,通过构造OutputStreamWriter指定编码格式,解决了乱码的问题。同样使用store()方法保存Properties对象,最后也要使用close()方法关闭输出流。

  总的来说,这两种方法的核心是使用Properties类提供的store()方法将Properties对象保存到文件中。但方法二相较于方法一更加灵活,能够解决编码问题。

应用场景案例

读取web.xml文件

  在web项目中,我们需要读取web.xml文件中的配置信息,例如servletlistener等配置信息。下面是一个读取web.xml文件中的servlet配置信息的示例代码:

public class ReadWebXml {
    public static void main(String[] args) throws Exception {
        Properties props = new Properties();
        InputStream in = new FileInputStream("web.xml");
        props.loadFromXML(in);
        in.close();

        Enumeration<?> en = props.propertyNames();
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            if (key.contains("servlet-name")) {
                String servletName = props.getProperty(key);
                String servletClass = props.getProperty(key.replace("name", "class"));
                System.out.println(servletName + " " + servletClass);
            }
        }
    }
}

  代码中读取web.xml文件时,使用loadFromXML()方法,读取XML格式的配置文件,具体读取方式和Properties相同。

写入Properties到数据库

  在Java中,我们经常将配置信息存储在数据库中,下面是一个将Properties写入MySQL数据库的示例代码:

public class WritePropertiesToDB {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        Properties props = new Properties();
        props.setProperty("ip", "127.0.0.1");
        props.setProperty("port", "3306");
        props.setProperty("username", "root");
        props.setProperty("password", "123456");

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname", "root", "123456");
        PreparedStatement ps = conn.prepareStatement("insert into config values(?,?,?,?)");
        Enumeration<?> en = props.propertyNames();
        int i = 1;
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            ps.setInt(1, i++);
            ps.setString(2, key);
            ps.setString(3, props.getProperty(key));
            ps.setDate(4, new Date(System.currentTimeMillis()));
            ps.executeUpdate();
        }
        ps.close();
        conn.close();
    }
}

  代码中,首先创建一个Properties对象,将配置信息存储在对象中。然后,使用JDBC连接MySQL数据库,将Properties中的键值对写入到数据库中。

优缺点分析

优点

  • 简单易用:Properties存储方式简单,易于阅读和修改。
  • 常用场景:Properties常用于存储配置文件和环境变量等常见场景。
  • 方便读写:Properties可以通过load()方法从文件中读取内容,也可以直接通过setProperty()方法添加键值对。

缺点

  • 存储方式有限:Properties只能存储字符串类型的键值对,无法存储其他类型的数据。
  • 不支持多线程:Properties不是线程安全的,不支持多线程操作,需要加锁保证安全。

类代码方法介绍

Properties类方法介绍

  • load(InputStream in):从输入流中读取属性列表(键和元素对)。
  • loadFromXML(InputStream in):从输入流中读取XML格式的属性列表(键和元素对)。
  • getProperty(String key):用指定的键在此属性列表中搜索属性。
  • setProperty(String key, String value):将指定的键值对写入到Properties中。
  • store(OutputStream out, String comments):将Properties写入到输出流中;comments为注释信息。
  • storeToXML(OutputStream os, String comment):将Properties写入到XML格式的输出流中;comment为注释信息。

InputStream类方法介绍

  • FileInputStream(String name):创建文件输入流。
  • BufferedInputStream(InputStream in):创建一个新的缓冲输入流,以将指定的输入流缓冲。
  • close():关闭此输入流并释放与该流关联的所有系统资源。

OutputStream类方法介绍

  • FileOutputStream(String name):创建文件输出流。
  • close():将此文件输出流关闭。在关闭流之前,将刷新此流。

PreparedStatement类方法介绍

  • executeUpdate():执行给定的SQL语句,该语句可能为INSERT、UPDATE或DELETE语句;或者不返回任何内容的SQL语句,如SQL DDL语句。

测试用例

  在编写代码时,为了避免出现错误,我们需要编写相应的测试用例。下面是一个测试文件读写的示例代码:

测试代码演示

package com.demo.javase.day65_5;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

/**
 * Properties示例演示
 *
 * @Author bug菌
 * @Date 2023-11-06 16:53
 */
public class PropertiesTest {

    public static void main(String[] args) throws IOException {
        testReadProperties();
        testWriteProperties();
    }

    // 测试读取Properties文件
    public static void testReadProperties() throws IOException {
        Properties props = new Properties();
        InputStream in = new FileInputStream("config/config.properties");
        props.load(new InputStreamReader(in, StandardCharsets.UTF_8));
        in.close();

        String ip = props.getProperty("ip");
        int port = Integer.parseInt(props.getProperty("port"));
        String username = props.getProperty("username");
        String password = props.getProperty("password");

        System.out.println("ip: " + ip);
        System.out.println("port: " + port);
        System.out.println("username: " + username);
        System.out.println("password: " + password);
    }

    // 测试写入Properties文件
    public static void testWriteProperties() throws IOException {
        Properties props = new Properties();
        props.setProperty("ip", "127.0.0.1");
        props.setProperty("port", "8080");
        props.setProperty("username", "admin");
        props.setProperty("password", "123456");

        OutputStream out = new FileOutputStream("config/newConfig.properties");
        props.store(new OutputStreamWriter(out, StandardCharsets.UTF_8), "New Config");
        out.close();
    }
}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

测试结果如下:

ip: 192.168.1.1
port: 8080
username: admin
password: 123456

  可以看出,读取Properties文件没有出现乱码问题;同时,写入Properties文件也成功了。

实际运行截图如下:

面对Properties的各种坑,你需要知道的Java小技巧

  然后我们来看newConfig.properties 文件,也成功被写入了指定的内容。

面对Properties的各种坑,你需要知道的Java小技巧

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

  该代码主要演示了如何使用Java中的Properties类读取和写入Properties文件。

  在testReadProperties方法中,首先创建一个Properties实例,并使用FileInputStream打开一个配置文件。然后,通过Properties.load方法从InputStream中读取属性值,并使用getProperty方法获取属性值。最后将获取到的属性值打印出来。

  在testWriteProperties方法中,同样创建一个Properties实例,并使用setProperty方法设置属性值。然后,使用FileOutputStream打开一个新的文件,通过Properties.store方法将属性值写入OutputStream中,并指定文件编码和文件注释。最后关闭文件输出流。

小结

  本文介绍了在使用Properties时需要注意的问题,例如读写乱码、键值对含有特殊字符等。我们可以通过代码示例和场景案例来更好地理解和掌握Properties的使用方法。使用Properties可以很方便地存储和读取配置信息,同时也需要注意线程安全和存储类型的限制等问题。

总结

  本文介绍了Java中常用的键值对存储方式——Properties,主要包括读取Properties时的乱码问题、处理键值对含有特殊字符的方法、写入Properties文件到数据库的示例代码等。在使用Properties时,需要注意存储类型的限制和线程安全等问题。本文还提供了测试用例和类方法介绍,帮助读者更加深入了解和掌握Properties的使用方法。

  ... ...

  好啦,这期的内容就基本接近尾声啦,若你想学习更多,你可以看看专栏的导读篇《「滚雪球学Java」教程导航帖》,本专栏致力打造最硬核 Java 零基础系列学习内容,🚀打造全网精品硬核专栏,带你直线超车;欢迎大家订阅持续学习。功不唐捐,久久为功!

「赠人玫瑰,手留余香」,咱们下期拜拜~~

附录源码

  如上涉及所有源码均已上传同步在「Gitee」,提供给同学们一对一参考学习,辅助你更迅速的掌握。

☀️建议/推荐你

  无论你是计算机专业的学生,还是对编程感兴趣的跨专业小白,都建议直接入手「滚雪球学Java」专栏;该专栏不仅免费,bug菌还郑重承诺,只要你学习此专栏,均能入门并理解Java SE,以全网最快速掌握Java语言,每章节源码均同步「Gitee」,你真值得拥有;学习就像滚雪球一样,越滚越大,带你指数级提升。

  码字不易,如果这篇文章对你有所帮助,帮忙给bugj菌来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。

📣关于我


面对Properties的各种坑,你需要知道的Java小技巧

转载自:https://juejin.cn/post/7368079196445655051
评论
请登录