首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java Properties 配置文件遍歷全攻略:三種核心方法與最佳實踐

     編輯:Java 程式設計入門

前言:Properties 在 Java 生態中的地位

java.util.Properties 是 Java 早期引入的配置管理類,繼承自 Hashtable<Object, Object>。雖然現代框架(Spring Boot、MicroProfile Config)提供了更強大的配置抽象,但 Properties 仍廣泛應用於:

  • 舊專案維護與遷移
  • 獨立工具類、腳本、測試代碼的輕量級配置
  • JVM 系統屬性(System.getProperties())
  • 國際化資源包(ResourceBundle 底層即基於 Properties)

掌握其遍歷方式,是 Java 開發者的基本功。

一、載入 Properties 文件的標準姿勢

Properties props = new Properties();
try (InputStream in = ClassLoader.getSystemResourceAsStream("wahaha.properties")) {
    if (in == null) throw new IllegalArgumentException("配置文件未找到");
    props.load(in); // ISO-8859-1 編碼
} catch (IOException e) {
    throw new UncheckedIOException(e);
}

注意: load(InputStream) 預設使用 ISO-8859-1 編碼。若配置含中文,需轉碼或使用 load(Reader) 指定 UTF-8:

try (Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
    props.load(reader);
}

二、三種核心遍歷方法深度解析

方法一:propertyNames() — 遍歷所有鍵(推薦)

Enumeration<?> keys = props.propertyNames(); // 返回 String 鍵的枚舉
while (keys.hasMoreElements()) {
    String key = (String) keys.nextElement();
    String value = props.getProperty(key); // 類型安全獲取值
    System.out.println(key + " = " + value);
}
  • 返回 Enumeration<String>(Java 8+ 泛型推斷)。
  • 僅包含「屬性鍵」,不包含繼承自 Hashtable 的非 String 鍵。
  • 配合 getProperty(key) 可獲取預設值、避免空指針。

方法二:elements() — 遍歷所有值(Hashtable 遺留)

Enumeration<?> values = props.elements(); // 返回 Object 值的枚舉
while (values.hasMoreElements()) {
    String value = (String) values.nextElement(); // 強轉有風險
    System.out.println(value);
}
  • 繼承自 Hashtable,返回所有值(包括非 String)。
  • 缺點: 無法獲取對應的鍵,類型不安全,不推薦常規業務使用。

方法三:entrySet() — 遍歷鍵值對(最通用、最強大)

Set<Map.Entry<Object, Object>> entries = props.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
    Object key = entry.getKey();
    Object value = entry.getValue();
    System.out.println(key + " : " + value);
}
  • 繼承自 Hashtable 實現 Map 接口。
  • 同時獲取鍵值,支援 Lambda/Stream 處理:
props.entrySet().forEach(e -> System.out.println(e.getKey() + "=" + e.getValue()));
// 或轉為 Map 進行流式操作
Map<String, String> map = props.entrySet().stream()
    .collect(Collectors.toMap(e -> (String)e.getKey(), e -> (String)e.getValue()));

三、實戰輸出對比

假設 wahaha.properties 內容:

name1=xxxx
name2=yyyyy
name3=zzzzzzz
方法輸出結果適用場景
propertyNames()name1
name2
name3
僅需遍歷鍵、或需配合 getProperty() 取值
elements()xxxx
yyyyy
zzzzzzz
極少用,僅需值且確信全為 String
entrySet()name1:xxxx
name2:yyyyy
name3:zzzzzzz
最通用,需鍵值對、轉 Map、流式處理

四、進階技巧與避坑指南

1. 類型安全獲取:getProperty(key, defaultVal)

int timeout = Integer.parseInt(props.getProperty("timeout", "3000")); // 預設 3000
boolean debug = Boolean.parseBoolean(props.getProperty("debug", "false"));

2. 屬性名稱前綴過濾

// 獲取所有以 "db." 開頭的屬性
props.stringPropertyNames().stream()
    .filter(k -> k.startsWith("db."))
    .forEach(k -> System.out.println(k + "=" + props.getProperty(k)));

3. 動態重載(熱更新)

public class ReloadableProps {
    private final AtomicReference<Properties> propsRef = new AtomicReference<>();
    private final Path path;
    private final WatchService watcher;

    public ReloadableProps(String filePath) throws IOException {
        this.path = Paths.get(filePath);
        this.watcher = FileSystems.getDefault().newWatchService();
        path.getParent().register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
        reload();
        new Thread(this::watchLoop).start();
    }
    // ... 實現 watchLoop 監聽修改並 reload()
}

4. 避坑:store() 寫入時的編碼與註釋

try (OutputStream out = new FileOutputStream("out.properties");
     Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8)) {
    props.store(writer, "更新時間: " + Instant.now()); // 註釋行以 # 開頭
}

store(OutputStream, comments) 同樣預設 ISO-8859-1,建議包裝 Writer 指定 UTF-8。

五、現代化替代:為什麼新專案建議用 Spring @ConfigurationProperties?

@ConfigurationProperties(prefix = "app")
@Data
public class AppConfig {
    private String name;
    private int port;
    private List<String> servers;
    private Map<String, String> labels;
}

優勢:類型安全、自動綁定、驗證(JSR-303)、熱重載(Spring Cloud Config)、IDE 提示、文檔化。Properties 遍歷僅作為底層理解與舊系統兼容之用。

結語

Properties 遍歷雖簡單,但細節決定質量:首選 propertyNames() 或 entrySet(),避免 elements();注意編碼問題;善用預設值與流式 API。 理解其 Hashtable 血統,有助於排查並發、序列化等邊界問題。新專務請擁抱類型安全的配置綁定框架,將精力集中在業務邏輯而非字串解析上。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved