Java 早期版本(JDK 6 及之前)無原生 API 設置文件隱藏屬性,常見做法是調用系統命令(Windows `attrib +H`、Unix/Linux 以 `.` 開頭命名)。JDK 7 引入 java.nio.file.attribute.FileAttribute 與 Files.setAttribute,實現了跨平台的隱藏文件創建。本文對比兩種方案並給出最佳實踐代碼。
| 維度 | Runtime.exec 系統命令 | NIO.2 Files.setAttribute (JDK 7+) |
|---|---|---|
| 跨平台 | 需區分 OS 編寫不同命令 | 統一 API,底層自動映射 |
| 權限要求 | 需命令執行權限,受安全管理器限制 | 僅需文件系統寫入權限 |
| 錯誤處理 | 進程返回碼、輸出流解析麻煩 | 標準 IOException 體系 |
| 性能 | 啟動進程開銷大 | 原生系統調用,輕量 |
| 適用版本 | JDK 1.0+ | JDK 7+ |
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;
public class HiddenFileCreator {
/**
* 跨平台創建隱藏文件
* Windows: 設置 dos:hidden 屬性
* Unix/Linux/macOS: 文件名以 '.' 開頭 (約定俗成),或設置 posix:hidden (極少數文件系統支持)
*/
public static Path createHiddenFile(String dirPath, String fileName) throws IOException {
Path dir = Paths.get(dirPath);
if (!Files.exists(dir)) {
Files.createDirectories(dir);
}
// Unix/Linux/macOS: 隱藏文件約定為以 '.' 開頭
String actualName = isWindows() ? fileName : "." + fileName;
Path filePath = dir.resolve(actualName);
// 創建空文件
Files.createFile(filePath);
// Windows 額外設置 hidden 屬性 (雙重保險)
if (isWindows()) {
try {
Files.setAttribute(filePath, "dos:hidden", true);
} catch (UnsupportedOperationException | IOException e) {
// 文件系統不支持 dos 屬性 (如 FAT32 某些情況),忽略
}
}
return filePath;
}
private static boolean isWindows() {
String os = System.getProperty("os.name").toLowerCase();
return os.contains("win");
}
// 測試
public static void main(String[] args) throws IOException {
Path hidden = createHiddenFile("D:/test", "secret.data");
System.out.println("隱藏文件已創建: " + hidden.toAbsolutePath());
System.out.println("是否隱藏(Windows): " + Files.isHidden(hidden)); // JDK 7+ 原生支持
}
}
public class LegacyHiddenFile {
public static void createHiddenFile(String absolutePath) throws IOException {
File file = new File(absolutePath);
if (file.exists()) file.delete();
file.createNewFile();
if (isWindows()) {
// Windows: attrib +H
String cmd = "attrib +H \"" + file.getAbsolutePath() + "\"";
Process p = Runtime.getRuntime().exec(cmd);
try { p.waitFor(); } catch (InterruptedException ignored) {}
} else {
// Unix: 重命名為 .開頭
File hidden = new File(file.getParent(), "." + file.getName());
file.renameTo(hidden);
}
}
}
// JDK 7+ 統一 API
boolean hidden = Files.isHidden(path);
// 手動檢查 (跨版本)
public static boolean isHidden(File file) {
if (isWindows()) {
try {
Process p = Runtime.getRuntime().exec("attrib \"" + file.getAbsolutePath() + "\"");
p.waitFor();
Scanner sc = new Scanner(p.getInputStream());
return sc.nextLine().contains("H");
} catch (Exception e) { return false; }
} else {
return file.getName().startsWith(".");
}
}
現代 Java 應用強烈建議基於 NIO.2 (`Files.setAttribute`, `Files.isHidden`) 實現隱藏文件創建與檢測,代碼簡潔、跨平台、異常處理規範。僅在維護極老舊系統(JDK 6)時才考慮 `Runtime.exec` 方案,並做好 OS 判斷與錯誤容忍。