前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面对Properties的各种坑,你需要知道的Java小技巧

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

原创
作者头像
bug菌
发布2024-08-06 09:02:53
2740
发布2024-08-06 09:02:53
举报
文章被收录于专栏:滚雪球学Java

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


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

代码语言:java
复制
环境说明: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示例:

代码语言:java
复制
#配置文件示例
ip=192.168.1.1
port=8080
username=admin
password=123456

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

代码语言:java
复制
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编码方式,如果我们的文件是其他编码方式,就会出现乱码。

在这里插入图片描述
在这里插入图片描述

解决方法如下:

代码语言: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中键值对含有特殊字符

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

下面是两种方法:

代码语言:java
复制
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()方法写入。

代码语言:java
复制
//方法一
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配置信息的示例代码:

代码语言:java
复制
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数据库的示例代码:

代码语言:java
复制
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语句。

测试用例

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

测试代码演示

代码语言:java
复制
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();
    }
}

测试结果

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

测试结果如下:

代码语言:java
复制
ip: 192.168.1.1
port: 8080
username: admin
password: 123456

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

实际运行截图如下:

在这里插入图片描述
在这里插入图片描述

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

测试代码分析

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

  该代码主要演示了如何使用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 零基础系列学习内容,🚀打造全网精品硬核专栏,带你直线超车;欢迎大家订阅持续学习。功不唐捐,久久为功!

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

☀️建议/推荐你

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学Java」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门Java编程,就像滚雪球一样,越滚越大,指数级提升。

  码字不易,如果这篇文章对你有所帮助,帮忙给bug菌来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。   同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!

📣关于我

  我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,掘金等平台签约作者,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计30w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。


--End

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 摘要
    • 源代码解析
      • 读取Properties乱码问题
      • Properties中键值对含有特殊字符
      • 写入Properties文件
    • 应用场景案例
      • 读取web.xml文件
      • 写入Properties到数据库
    • 优缺点分析
      • 优点
      • 缺点
    • 类代码方法介绍
      • Properties类方法介绍
      • InputStream类方法介绍
      • OutputStream类方法介绍
      • PreparedStatement类方法介绍
    • 测试用例
      • 测试代码演示
      • 测试结果
      • 测试代码分析
    • 小结
    • 总结
    • ☀️建议/推荐你
    • 📣关于我
    相关产品与服务
    云数据库 MySQL
    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档