# file-system
**Repository Path**: MineLX/file-system
## Basic Information
- **Project Name**: file-system
- **Description**: easier, more natural and functional api for general filesystems interacting.
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-09-28
- **Last Updated**: 2026-04-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# File System
[](http://www.apache.org/licenses/LICENSE-2.0)
[](https://www.oracle.com/java/)
一个更简单、更自然、更功能化的通用文件系统交互 API。
## ✨ 特性
- 🎯 **链式调用** - 流畅的 API 设计,让路径导航和资源定位变得极其简单
- 🔧 **OpenPolicy 策略模式** - 统一的访问控制策略,适用于所有文件和目录操作
- 🛡️ **类型安全** - 明确区分 File、Directory 和 Path,编译期即可发现错误
- 🔄 **自动资源管理** - TempPath 实现 AutoCloseable,确保临时文件自动清理
- 🌐 **可扩展架构** - 支持多种文件系统后端,轻松扩展自定义文件系统
## 🚀 快速开始
### Maven 依赖
```xml
io.gitee.minelx
file-system
1.0.1
```
### 基础示例
```java
import io.gitee.minelx.filesystem.*;
import io.gitee.minelx.filesystem.init.OpenPolicy;
import io.gitee.minelx.filesystem.provider.FS;
import java.nio.charset.StandardCharsets;
// 简单的文件读写
Directory root = FS.workingDir()
.child().dir("data", OpenPolicy.CREATE_IF_NOT_EXISTED);
File file = root.child().file("hello.txt", OpenPolicy.CREATE_IF_NOT_EXISTED);
file.write("Hello, World!", StandardCharsets.UTF_8);
String content = file.read(StandardCharsets.UTF_8);
System.out.println(content); // 输出: Hello, World!
```
## 🎯 核心设计理念
### 1. 链式调用 - 让路径导航如丝般顺滑
传统的文件操作需要拼接路径字符串,容易出错且难以阅读。File System 通过 **Locator** 和 **链式调用** 让路径导航变得直观优雅:
```java
// ❌ 传统方式 - 路径拼接易出错
String path = "/home/user/projects/myapp/config/database.yml";
File file = new File(path);
// ✅ File System 方式 - 清晰的链式调用
File configFile = FS.workingDir()
.child().dir("home", OpenPolicy.EXISTS)
.child().dir("user", OpenPolicy.EXISTS)
.child().dir("projects", OpenPolicy.EXISTS)
.child().dir("myapp", OpenPolicy.EXISTS)
.child().dir("config", OpenPolicy.EXISTS)
.child().file("database.yml", OpenPolicy.CREATE_IF_NOT_EXISTED);
```
**链式调用的优势:**
- 📖 **可读性强** - 每一步操作都清晰可见
- 🔍 **易于调试** - 可以在任何环节断点检查
- 🛠️ **灵活组合** - 轻松构建复杂的路径逻辑
- ⚡ **IDE 友好** - 完整的代码提示和自动补全
更多链式调用示例:
```java
// 目录遍历和处理
FS.workingDir()
.child().dir("logs", OpenPolicy.EXISTS)
.children()
.filter(path -> path.name().endsWith(".log"))
.forEach(path -> {
System.out.println("找到日志文件: " + path.name());
});
// 快速定位深层资源
Directory deepDir = FS.local()
.dir("var", OpenPolicy.EXISTS)
.child().dir("lib", OpenPolicy.EXISTS)
.child().dir("docker", OpenPolicy.EXISTS);
// 路径导航
Path currentPath = file.path();
Path siblingPath = currentPath.sibling("backup.txt"); // 兄弟文件
Directory parentDir = currentPath.container(); // 父目录
Path renamedPath = currentPath.rename("new_name.txt"); // 重命名
```
### 2. OpenPolicy - 一套策略,处处适用
**OpenPolicy** 是 File System 的核心创新之一。它提供统一的访问控制策略,适用于所有文件和目录操作,让你能够精确控制资源的打开行为:
```java
public enum OpenPolicy {
EXISTS, // 要求资源必须存在且类型匹配
CREATE, // 创建新资源(已存在则报错)
CREATE_IF_NOT_EXISTED, // 不存在则创建,存在则验证类型
__ // 无检查(自由模式)
}
```
#### 策略详解
**EXISTS** - 严格模式,确保资源已存在
```java
// 读取配置文件,如果不存在立即失败
File config = dir.child().file("config.json", OpenPolicy.EXISTS);
String content = config.read(StandardCharsets.UTF_8);
// 打开已有目录
Directory logs = dir.child().dir("logs", OpenPolicy.EXISTS);
```
**CREATE** - 创建模式,确保资源是新创建的
```java
// 创建新文件,如果已存在会抛出异常(防止意外覆盖)
File newFile = dir.child().file("report.txt", OpenPolicy.CREATE);
newFile.write("报告内容", StandardCharsets.UTF_8);
// 创建新目录
Directory output = dir.child().dir("output", OpenPolicy.CREATE);
```
**CREATE_IF_NOT_EXISTED** - 智能模式,最常用
```java
// 最常用的策略:不存在就创建,存在就验证类型
File dataFile = dir.child().file("data.json", OpenPolicy.CREATE_IF_NOT_EXISTED);
Directory cacheDir = dir.child().dir("cache", OpenPolicy.CREATE_IF_NOT_EXISTED);
// 适合初始化场景
Directory appDir = FS.workingDir()
.child().dir("myapp", OpenPolicy.CREATE_IF_NOT_EXISTED)
.child().dir("config", OpenPolicy.CREATE_IF_NOT_EXISTED);
```
**__** - 自由模式,不做任何检查
```java
// 用于特殊场景,完全由开发者控制
Path anyPath = dir.child().path("anything", OpenPolicy.__);
```
#### OpenPolicy 的通用性
**所有资源操作都使用相同的策略接口**,无论是文件还是目录:
```java
// ✅ 文件操作
File file1 = dir.child().file("a.txt", OpenPolicy.CREATE_IF_NOT_EXISTED);
File file2 = dir.child().file("b.txt", OpenPolicy.EXISTS);
File file3 = dir.child().file("c.txt", OpenPolicy.CREATE);
// ✅ 目录操作 - 使用完全相同的策略
Directory dir1 = dir.child().dir("folder1", OpenPolicy.CREATE_IF_NOT_EXISTED);
Directory dir2 = dir.child().dir("folder2", OpenPolicy.EXISTS);
Directory dir3 = dir.child().dir("folder3", OpenPolicy.CREATE);
// ✅ Locator 统一接口
Locator locator = dir.child();
File f = locator.file("test.txt", OpenPolicy.CREATE_IF_NOT_EXISTED);
Directory d = locator.dir("test_dir", OpenPolicy.CREATE_IF_NOT_EXISTED);
```
**策略带来的好处:**
- 🎯 **一致性** - 文件和目录使用相同的策略语义
- 🛡️ **安全性** - 在打开时就验证状态,避免后续操作失败
- 💡 **意图明确** - 代码即文档,一眼看出资源预期状态
- 🔧 **灵活性** - 根据不同场景选择合适的策略
## 📚 完整使用指南
### 文件操作
```java
// 创建和写入
File file = root.child().file("example.txt", OpenPolicy.CREATE_IF_NOT_EXISTED);
file.write("Hello, File System!", StandardCharsets.UTF_8);
// 读取内容
String content = file.read(StandardCharsets.UTF_8);
// 流式操作
try (InputStream input = file.inputStream()) {
// 处理输入流
}
try (OutputStream output = file.outputStream(StandardOpenOption.CREATE)) {
output.write("数据".getBytes(StandardCharsets.UTF_8));
}
// 文件判断
boolean isEmpty = file.empty();
boolean isJson = file.isExtensionOf("json");
// 获取路径信息
Path path = file.path();
String name = path.name();
String absolutePath = path.absolutePath();
```
### 目录操作
```java
// 创建目录
Directory dir = root.child().dir("mydir", OpenPolicy.CREATE_IF_NOT_EXISTED);
// 列出子项
String[] names = dir.childrenNames();
Stream children = dir.children();
// 目录管理
boolean isEmpty = dir.empty();
dir.clear(); // 清空目录
// 获取定位器继续导航
Locator childLocator = dir.child();
File subFile = childLocator.file("sub.txt", OpenPolicy.CREATE);
```
### 临时文件管理
```java
// 自动清理的临时文件(推荐)
try (TempPath tempPath = TempPath.random()) {
File tempFile = tempPath.file();
tempFile.write("临时数据", StandardCharsets.UTF_8);
// 退出 try 块后自动删除
}
// 带初始内容的临时文件
try (TempPath tempPath = TempPath.random("初始内容")) {
// 文件已包含"初始内容"
}
// 指定名称的临时文件
try (TempPath tempPath = TempPath.of("my_temp.txt")) {
File tempFile = tempPath.file();
// 使用临时文件...
}
```
### 实战示例
#### 示例 1:配置文件管理器
```java
public class ConfigManager {
private Directory configDir;
public ConfigManager() {
this.configDir = FS.workingDir()
.child().dir("config", OpenPolicy.CREATE_IF_NOT_EXISTED);
}
public void saveConfig(String key, String value) throws IOException {
File configFile = configDir.child()
.file(key + ".json", OpenPolicy.CREATE_IF_NOT_EXISTED);
configFile.write(value, StandardCharsets.UTF_8);
}
public String loadConfig(String key) throws IOException {
File configFile = configDir.child()
.file(key + ".json", OpenPolicy.EXISTS);
return configFile.read(StandardCharsets.UTF_8);
}
public boolean hasConfig(String key) {
return configDir.child().path(key + ".json").exists();
}
}
```
#### 示例 2:日志文件处理器
```java
public class LogProcessor {
private Directory logDir;
public LogProcessor() {
this.logDir = FS.workingDir()
.child().dir("logs", OpenPolicy.CREATE_IF_NOT_EXISTED);
}
public void writeLog(String level, String message) throws IOException {
String date = LocalDate.now().toString();
File logFile = logDir.child()
.file(date + ".log", OpenPolicy.CREATE_IF_NOT_EXISTED);
String logEntry = String.format("[%s] %s: %s%n",
LocalDateTime.now(), level, message);
try (OutputStream os = logFile.outputStream(StandardOpenOption.APPEND)) {
os.write(logEntry.getBytes(StandardCharsets.UTF_8));
}
}
public List readLogs(LocalDate date) throws IOException {
File logFile = logDir.child()
.file(date.toString() + ".log", OpenPolicy.EXISTS);
String content = logFile.read(StandardCharsets.UTF_8);
return Arrays.asList(content.split("\n"));
}
public void cleanupOldLogs(int daysToKeep) {
LocalDate cutoff = LocalDate.now().minusDays(daysToKeep);
logDir.children()
.filter(path -> {
try {
String fileName = path.name().replace(".log", "");
LocalDate fileDate = LocalDate.parse(fileName);
return fileDate.isBefore(cutoff);
} catch (Exception e) {
return false;
}
})
.forEach(Path::delete);
}
}
```
#### 示例 3:批量文件转换
```java
public class FileConverter {
public void convertAllTxtToJson(Directory sourceDir, Directory targetDir)
throws IOException {
sourceDir.children()
.filter(path -> path.name().endsWith(".txt"))
.forEach(path -> {
try {
File txtFile = File.create(path, OpenPolicy.EXISTS);
String content = txtFile.read(StandardCharsets.UTF_8);
String jsonName = path.name().replace(".txt", ".json");
File jsonFile = targetDir.child()
.file(jsonName, OpenPolicy.CREATE);
String jsonContent = convertToJson(content);
jsonFile.write(jsonContent, StandardCharsets.UTF_8);
System.out.println("转换完成: " + path.name());
} catch (IOException e) {
System.err.println("转换失败: " + path.name());
e.printStackTrace();
}
});
}
private String convertToJson(String text) {
// 转换逻辑...
return "{\"content\":\"" + text + "\"}";
}
}
```
## 🏗️ 架构设计
### 核心类关系
```
FS (文件系统接口)
└─ Locator (路径定位器)
├─ Path (路径抽象)
│ ├─ File (文件操作)
│ └─ Directory (目录操作)
└─ TempPath (临时文件管理)
OpenPolicy (访问策略)
├─ EXISTS
├─ CREATE
├─ CREATE_IF_NOT_EXISTED
└─ __
```
### 扩展文件系统
```java
// 实现自定义文件系统
public class MyCustomFS implements FS {
@Override
public String schemaAndAuthority() {
return "myfs://";
}
@Override
public PathMethodProvider provider(PathDescription description) {
return new MyCustomPathMethodProvider(description);
}
}
// 使用自定义文件系统
FS customFS = new MyCustomFS();
Directory dir = customFS.locate()
.dir("/path", OpenPolicy.CREATE_IF_NOT_EXISTED);
```
## 📊 API 速查
### FS - 文件系统入口
```java
FS.LOCAL_FS // 本地文件系统
FS.local() // 获取本地定位器
FS.workingDir() // 获取工作目录
FS.of(javaFileSystem) // 包装 Java NIO FileSystem
```
### OpenPolicy - 访问策略
```java
OpenPolicy.EXISTS // 要求存在
OpenPolicy.CREATE // 创建新的
OpenPolicy.CREATE_IF_NOT_EXISTED // 智能创建
OpenPolicy.__ // 无检查
```
### Path - 路径操作
```java
path.uri() // 获取 URI
path.exists() // 判断存在
path.name() // 获取名称
path.absolutePath() // 获取绝对路径
path.sibling(name) // 兄弟路径
path.container() // 父目录
path.rename(name) // 重命名
path.delete() // 删除
path.deleteIfExists() // 安全删除
```
### File - 文件操作
```java
File.create(path, policy) // 创建文件
file.read(charset) // 读取内容
file.write(content, charset) // 写入内容
file.write(inputStream) // 写入流
file.inputStream() // 获取输入流
file.outputStream(option) // 获取输出流
file.empty() // 判断是否为空
file.isExtensionOf(ext) // 判断扩展名
```
### Directory - 目录操作
```java
Directory.create(path, policy) // 创建目录
dir.childrenNames() // 获取子项名称
dir.children() // 获取子项流
dir.empty() // 判断是否为空
dir.clear() // 清空目录
dir.child() // 获取定位器
```
### TempPath - 临时文件
```java
TempPath.random() // 随机临时文件
TempPath.random(content) // 带内容的随机文件
TempPath.of(fileName) // 指定名称的临时文件
tempPath.file() // 获取文件对象
tempPath.dir() // 获取目录对象
tempPath.close() // 清理(AutoCloseable)
```
## 🧪 测试
```bash
mvn test
```
## 📄 许可证
本项目采用 [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) 开源协议。
## 🤝 贡献
欢迎提交 Issue 和 Pull Request!
## 📮 联系方式
- 作者: MineLX
- 邮箱: 2647389011@qq.com
- 项目地址: https://gitee.com/MineLX/file-system
---
**享受简洁优雅的文件系统操作体验!** 🎉