杰瑞科技汇

Java如何高效读取properties文件?

什么是 Properties 文件?

properties 文件是一种简单的、基于文本的配置文件,通常用于存储应用程序的配置信息,例如数据库连接信息、API密钥、开关设置等。

Java如何高效读取properties文件?-图1
(图片来源网络,侵删)

它的特点是:

  • 键值对存储:格式为 key = valuekey:value
  • 注释:使用 或 开头表示单行注释。
  • 编码:通常使用 ISO-8859-1 编码,但可以存储 Unicode 字符(通过 \uXXXX 转义)。

示例:config.properties

# Database Configuration
db.url=jdbc:mysql://localhost:3306/mydb
db.username=admin
db.password=secret123
db.pool.size=10
# Application Settings
app.name=My Awesome App
app.version=1.2.0
feature.new.enabled=true

使用 java.util.Properties 类(最传统、最经典)

这是最基础、最核心的方法,适用于所有 Java 版本,它通过 InputStream 读取文件内容。

关键步骤:

  1. 创建一个 Properties 对象。
  2. 使用 ClassLoader 获取文件的 InputStream这是最推荐的方式,因为它能确保从类路径(src/main/resources)中正确加载文件,无论是在开发环境还是打包后的 JAR/WAR 文件中。
  3. 调用 load(InputStream) 方法将输入流中的内容加载到 Properties 对象中。
  4. 使用 getProperty(String key)getProperty(String key, String defaultValue) 方法获取值。

完整代码示例:

项目结构:

Java如何高效读取properties文件?-图2
(图片来源网络,侵删)
src/
└── main/
    ├── java/
    │   └── com/
    │       └── example/
    │           └── PropertiesReader.java
    └── resources/
        └── config.properties

PropertiesReader.java

package com.example;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesReader {
    public static void main(String[] args) {
        // 1. 创建 Properties 对象
        Properties props = new Properties();
        // try-with-resources 语句可以自动关闭流,避免资源泄漏
        try (InputStream input = PropertiesReader.class.getClassLoader().getResourceAsStream("config.properties")) {
            // 2. 检查文件是否存在
            if (input == null) {
                System.out.println("Sorry, unable to find config.properties");
                return;
            }
            // 3. 加载 properties 文件内容
            props.load(input);
            // 4. 读取并打印配置项
            System.out.println("Database URL: " + props.getProperty("db.url"));
            System.out.println("Database User: " + props.getProperty("db.username"));
            System.out.println("App Name: " + props.getProperty("app.name"));
            System.out.println("App Version: " + props.getProperty("app.version"));
            // 5. 获取属性,如果不存在则返回默认值
            String featureFlag = props.getProperty("feature.new.enabled", "false");
            System.out.println("New Feature Enabled: " + featureFlag);
            // 获取一个不存在的属性,会返回 null
            String nonExistent = props.getProperty("non.existent.key");
            System.out.println("Non-existent Key: " + nonExistent);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

为什么使用 getClassLoader().getResourceAsStream()

  • 路径是相对于类根目录的:对于 Maven/Gradle 项目,src/main/resources 目录下的文件在编译后会直接进入类路径的根目录。
  • 环境无关性:无论你的代码是在 IDE 中运行,还是被打包成 JAR 文件运行,这种方式都能正确找到文件,如果你使用 new FileInputStream("config.properties"),路径是相对于当前工作目录的,这在 JAR 包运行时很容易出错。

使用 java.util.ResourceBundle 类(国际化友好)

ResourceBundle 专门用于本地化,但它也可以非常方便地读取 properties 文件,它不直接处理文件流,而是通过文件名来加载。

关键步骤:

  1. properties 文件必须遵循特定的命名规则:basename_<locale>.propertiesconfig_en_US.properties,默认的(不带语言环境的)文件是 config.properties
  2. 使用 ResourceBundle.getBundle("basename") 来加载,JVM 会根据默认的 Locale 自动寻找最匹配的文件。
  3. 使用 getString(String key) 获取字符串值。

完整代码示例:

假设你的 config.properties 文件在 src/main/resources 下。

Java如何高效读取properties文件?-图3
(图片来源网络,侵删)

ResourceBundleReader.java

package com.example;
import java.util.ResourceBundle;
public class ResourceBundleReader {
    public static void main(String[] args) {
        // "config" 是文件名,不包含 .properties 后缀
        // ResourceBundle 会自动从类路径中查找 config.properties
        ResourceBundle rb = ResourceBundle.getBundle("config");
        System.out.println("App Name from ResourceBundle: " + rb.getString("app.name"));
        System.out.println("Database URL from ResourceBundle: " + rb.getString("db.url"));
        // 如果键不存在,会抛出 MissingResourceException
        // System.out.println(rb.getString("non.existent.key")); 
    }
}

优点

  • 简洁,无需处理流和异常。
  • 为国际化(i18n)提供了完美的支持。

缺点

  • 只能读取字符串值,对于 Integer, Boolean 等类型,需要手动转换。
  • 文件命名规则严格。

使用 Spring Framework 的 @Value 注解(在 Spring/Spring Boot 环境中)

如果你的项目是基于 Spring 或 Spring Boot 的,这是最优雅、最推荐的方式,它允许你直接将 properties 文件中的值注入到字段中。

步骤:

  1. 确保你的 properties 文件位于 src/main/resources 目录下。
  2. 在 Spring Boot 项目中,默认会加载 application.propertiesapplication.yml,你也可以自定义文件名。
  3. 使用 @Value("${key:default_value}") 注解来注入属性。

完整代码示例:

application.properties

myapp.name=Spring Boot App
myapp.message=Hello from Spring!
feature.flag=true

SpringPropertiesService.java

package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service // 声明为 Spring 服务组件
public class SpringPropertiesService {
    // 从 application.properties 中读取 myapp.name,如果不存在则使用 "Default App"
    @Value("${myapp.name:Default App}")
    private String appName;
    // 读取一个字符串
    @Value("${myapp.message}")
    private String message;
    // 读取一个布尔值,Spring 会自动转换
    @Value("${feature.flag:false}")
    private boolean featureEnabled;
    // 读取一个数字,Spring 会自动转换
    @Value("${db.pool.size:10}")
    private int poolSize;
    public void printProperties() {
        System.out.println("App Name: " + appName);
        System.out.println("Message: " + message);
        System.out.println("Feature Enabled: " + featureEnabled);
        System.out.println("Pool Size: " + poolSize);
    }
}

如何运行(需要 Spring 环境) 你需要一个 Spring Boot 应用来启动这个服务。


总结与最佳实践

方法 适用场景 优点 缺点
java.util.Properties 通用、任何 Java 项目 核心基础,灵活,可读取任何值(需转换) 需要手动处理流和异常,代码稍显冗长
java.util.ResourceBundle 需要国际化支持的项目 代码简洁,自动处理本地化 只能读字符串,文件命名有要求
@Value (Spring) Spring / Spring Boot 项目 最优雅,与框架深度集成,自动类型转换 仅限 Spring 环境

如何选择?

  1. 如果你在一个普通的 Java SE 项目中(没有使用 Spring 框架)

    • 首选 java.util.Properties,这是最可靠、最标准的方式。
    • 如果你的应用有多个语言版本,并且需要根据用户语言切换配置,可以考虑 ResourceBundle
  2. 如果你在一个 Spring 或 Spring Boot 项目中

    • 毫不犹豫地使用 @Value 注解,它能让你在代码中直接使用配置值,非常直观和方便,Spring Boot 还支持 @ConfigurationProperties 来将一组相关的属性绑定到一个类型安全的配置类中,这是更进阶的做法。
  3. 文件路径的最佳实践

    • 始终将 properties 文件放在 src/main/resources 目录下。
    • 始终使用 ClassLoader.getResourceAsStream()ResourceBundle 来加载,确保路径的正确性。避免使用绝对路径或相对于项目根目录的相对路径
分享:
扫描分享到社交APP
上一篇
下一篇