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

Java Properties 配置文件讀寫完全指南:從入門到 XML 持久化

     編輯:Java 相關知識

前言

Properties 是 Java 平台處理配置文件的標準工具類,繼承自 Hashtable,鍵值皆為 String。廣泛應用於:資料庫連線參數、系統開關、國際化資源、外部化配置。本文系統講解 Properties 核心 API、檔案操作、XML 持久化、最佳實踐與避坑指南。

一、Properties 核心特性

  • extends Hashtable<Object,Object> → 基本 Map 操作皆可用
  • 鍵值必須為 String (put 會自動 toString,建議用 setProperty/getProperty)
  • 支援 # 或 ! 開頭的註解行
  • 支援 \ 續行、Unicode 轉義 (\uXXXX)
  • 預設編碼 ISO-8859-1 (Java 9+ load/fromInputStream 可指定編碼)

二、基礎 API 操作

Properties props = new Properties();

// 設值 (推薦)
props.setProperty("db.url", "jdbc:mysql://localhost:3306/mydb");
props.setProperty("db.user", "root");
props.setProperty("db.password", "secret");

// 取值 (含預設值)
String url = props.getProperty("db.url", "jdbc:h2:mem:test"); // 不存在回傳預設值
String driver = props.getProperty("db.driver"); // 不存在回傳 null

// 遍歷
props.forEach((k, v) -> System.out.println(k + "=" + v));
// 或
for (String name : props.stringPropertyNames()) {
    System.out.println(name + "=" + props.getProperty(name));
}

// 刪除
props.remove("db.password"); // 繼承自 Hashtable

三、檔案載入與儲存

1. 載入 .properties 檔案


// 傳統寫法 (ISO-8859-1 編碼,中文會亂碼)
try (FileInputStream fis = new FileInputStream("config.properties")) {
    props.load(fis);
}

// Java 9+ 指定 UTF-8 (推薦)
try (FileReader fr = new FileReader("config.properties", StandardCharsets.UTF_8)) {
    props.load(fr);
}

// 從 classpath 載入 (常見於 Spring @PropertySource)
try (InputStream is = getClass().getClassLoader().getResourceAsStream("app.properties")) {
    if (is != null) props.load(is);
}

2. 儲存為 .properties

try (FileWriter fw = new FileWriter("config.properties", StandardCharsets.UTF_8)) {
    props.store(fw, "Database Configuration - Updated " + new Date());
}
// 輸出範例:
// #Database Configuration - Updated Mon May 20 10:30:00 CST 2024
// db.password=secret
// db.url=jdbc:mysql://localhost:3306/mydb
// db.user=root

3. XML 持久化 (結構化、支援 UTF-8 無亂碼)

// 寫入 XML
try (FileOutputStream fos = new FileOutputStream("config.xml")) {
    props.storeToXML(fos, "Database Config", StandardCharsets.UTF_8.name());
}

// 從 XML 載入
try (FileInputStream fis = new FileInputStream("config.xml")) {
    props.loadFromXML(fis);
}

XML 輸出範例:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "https://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>Database Config</comment>
    <entry key="db.url">jdbc:mysql://localhost:3306/mydb</entry>
    <entry key="db.user">root</entry>
    <entry key="db.password">secret</entry>
</properties>

四、進階用法與模式

1. 系統屬性疊加 (System.getProperties())

Properties sysProps = System.getProperties();
Properties appProps = new Properties(sysProps); // 繼承系統屬性作為預設值
appProps.load(new FileInputStream("app.properties"));
// appProps 可讀取系統屬性,自身修改不影響系統屬性

2. 多環境配置隔離

// 應用啟動時根據 -Denv=prod 載入對應配置
String env = System.getProperty("env", "dev");
Properties props = new Properties();
props.load(new FileInputStream("application.properties"));      // 基礎配置
props.load(new FileInputStream("application-" + env + ".properties")); // 環境覆蓋

3. 類型安全轉換輔助

public class PropsHelper {
    private final Properties props;
    public PropsHelper(Properties props) { this.props = props; }
    
    public int getInt(String key, int def) {
        String v = props.getProperty(key);
        return v != null ? Integer.parseInt(v) : def;
    }
    public long getLong(String key, long def) { /* ... */ }
    public boolean getBool(String key, boolean def) { /* ... */ }
    public List getList(String key, String delimiter) { /* ... */ }
}

4. 動態重載 (配置熱更新)

public class ReloadableProps {
    private final String filePath;
    private volatile Properties props;
    private long lastModified;
    
    public ReloadableProps(String filePath) { this.filePath = filePath; reload(); }
    
    public synchronized void reload() {
        File f = new File(filePath);
        if (f.lastModified() > lastModified) {
            Properties newProps = new Properties();
            try (FileReader fr = new FileReader(f, StandardCharsets.UTF_8)) {
                newProps.load(fr);
                this.props = newProps;
                this.lastModified = f.lastModified();
            } catch (IOException e) { log.error("重載失敗", e); }
        }
    }
    
    public String get(String key) { reload(); return props.getProperty(key); }
}

五、編碼問題徹底解決

場景問題解決方案
Properties 檔含中文ISO-8859-1 讀取亂碼Java 9+ 用 FileReader(StandardCharsets.UTF_8) / Files.newBufferedReader
舊專案必須用 .properties無法直接存 UTF-8用 native2ascii 轉義 \uXXXX、或改用 XML 格式
ResourceBundle 讀取強制 ISO-8859-1改用 Properties.load(InputStream) 自行控制編碼

六、最佳實踐清單

  1. 統一 UTF-8:Java 9+ 全面使用 Files.newBufferedReader/Writer
  2. 優先 XML:原生支援 UTF-8、結構化、可驗證 DTD
  3. 分層配置:default → application → application-{env} → 系統屬性 → 環境變數
  4. 敏感資訊外部化:密碼、金鑰放環境變數/密碼管理系統,不入倉庫
  5. 類型轉換封裝:提供 getInt/getBool 避免散落 parse 邏輯
  6. 熱更新可選:長運行服務考慮檔案監聽重載 (WatchService)
  7. 單例模式:配置載入一次,全域共享不可變實例

七、完整範例:配置管理器

public final class ConfigManager {
    private static final ConfigManager INSTANCE = new ConfigManager();
    private final Properties props = new Properties();
    
    private ConfigManager() {
        load("application.properties");
        String env = System.getProperty("app.env", "dev");
        load("application-" + env + ".properties");
        // 系統屬性最高優先級覆蓋
        props.putAll(System.getProperties());
    }
    
    private void load(String path) {
        try (InputStream is = getClass().getClassLoader().getResourceAsStream(path)) {
            if (is != null) props.load(is);
        } catch (IOException e) { log.warn("配置載入失敗:{}", path, e); }
    }
    
    public static ConfigManager get() { return INSTANCE; }
    public String getString(String key) { return props.getProperty(key); }
    public String getString(String key, String def) { return props.getProperty(key, def); }
    public int getInt(String key, int def) { /* ... */ }
    // ... 其他類型轉換
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved