JDK 5.0 引入 ProcessBuilder,取代笨重的 Runtime.exec(),提供更直觀的 API 控制外部程序啟動、環境變數、工作目錄、輸入輸出重導向。本文以 Windows 下讀取網卡 MAC 位址為例實戰演示。
environment() 直接操作環境變數 Mapdirectory(File) 指定工作目錄redirectInput/Output/Error 靈活重導向流start() 一行package com.example.jdk5;
import java.io.*;
import java.util.*;
public class ProcessBuilderDemo {
public static List<String> getPhysicalAddresses() {
List<String> addresses = new ArrayList<>();
Process process = null;
try {
// 啟動 ipconfig /all
process = new ProcessBuilder("ipconfig", "/all").start();
} catch (IOException e) {
return addresses; // 空列表
}
// 讀取標準輸出
StringBuilder output = new StringBuilder();
try (InputStream in = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
} catch (IOException e) {
// 忽略讀取錯誤
}
// 解析輸出尋找 Physical Address
String content = output.toString();
String keyword = "Physical Address";
int idx = content.indexOf(keyword);
while (idx >= 0) {
// 跳過關鍵字與分隔符,取後 17 字元 (XX-XX-XX-XX-XX-XX)
int start = content.indexOf(":", idx) + 2;
if (start > 1 && start + 17 <= content.length()) {
addresses.add(content.substring(start, start + 17).trim());
}
idx = content.indexOf(keyword, idx + 1);
}
return addresses;
}
public static void main(String[] args) {
List<String> macs = getPhysicalAddresses();
for (String mac : macs) {
System.out.printf("實體網卡 MAC: %s%n", mac);
}
}
}
start() 回傳 Process 物件,非阻塞。BufferedReader 逐行讀取,比固定位元組陣列更穩健。ipconfig /all,Linux/Mac 用 ifconfig 或 ip link,關鍵字與輸出格式不同,實際專案需判斷 System.getProperty("os.name") 分流處理。| 需求 | API |
|---|---|
| 設定環境變數 | pb.environment().put("VAR", "value") |
| 指定工作目錄 | pb.directory(new File("/path")) |
| 合併錯誤輸出到標準輸出 | pb.redirectErrorStream(true) |
| 輸出導向檔案 | pb.redirectOutput(ProcessBuilder.Redirect.to(file)) |
| 等待結束並取得退出碼 | process.waitFor() |
ProcessBuilder 讓 Java 與系統原生指令互動更優雅、安全,是系統管理、自動化腳本、整合舊系統的利器。