|
|
|
|
|
# 路径格式更新说明
|
|
|
|
|
|
|
|
|
|
|
|
## 更新日期
|
|
|
|
|
|
2025-03-25
|
|
|
|
|
|
|
|
|
|
|
|
## 更新内容
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 文件保存路径格式变更
|
|
|
|
|
|
|
|
|
|
|
|
#### 原路径格式
|
|
|
|
|
|
```
|
|
|
|
|
|
basePath/SN_type_timestamp.ext
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**示例:**
|
|
|
|
|
|
```
|
|
|
|
|
|
D:/output/192.168.1.100_pointcloud_20250325_143022.pcd
|
|
|
|
|
|
D:/output/192.168.1.100_rgb_20250325_143022.png
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 新路径格式
|
|
|
|
|
|
```
|
|
|
|
|
|
basePath/日期/类型/SN_type_timestamp.ext
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**示例:**
|
|
|
|
|
|
```
|
|
|
|
|
|
D:/output/20250325/pointCloud/192.168.1.100_pointcloud_20250325_143022.pcd
|
|
|
|
|
|
D:/output/20250325/rgb/192.168.1.100_rgb_20250325_143022.png
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 目录结构变化
|
|
|
|
|
|
|
|
|
|
|
|
#### 原结构
|
|
|
|
|
|
```
|
|
|
|
|
|
D:/output/
|
|
|
|
|
|
├── 192.168.1.100_pointcloud_20250325_143022.pcd
|
|
|
|
|
|
├── 192.168.1.100_rgb_20250325_143022.png
|
|
|
|
|
|
├── 192.168.1.101_pointcloud_20250325_143023.pcd
|
|
|
|
|
|
└── ...
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 新结构
|
|
|
|
|
|
```
|
|
|
|
|
|
D:/output/
|
|
|
|
|
|
├── 20250325/
|
|
|
|
|
|
│ ├── amplitude/
|
|
|
|
|
|
│ │ ├── 192.168.1.100_amplitude_20250325_143022.png
|
|
|
|
|
|
│ │ └── ...
|
|
|
|
|
|
│ ├── rgb/
|
|
|
|
|
|
│ │ ├── 192.168.1.100_rgb_20250325_143022.png
|
|
|
|
|
|
│ │ └── ...
|
|
|
|
|
|
│ ├── depth/
|
|
|
|
|
|
│ │ ├── 192.168.1.100_depth_20250325_143022.png
|
|
|
|
|
|
│ │ └── ...
|
|
|
|
|
|
│ ├── depthColor/
|
|
|
|
|
|
│ │ ├── 192.168.1.100_depth_color_20250325_143022.png
|
|
|
|
|
|
│ │ └── ...
|
|
|
|
|
|
│ └── pointCloud/
|
|
|
|
|
|
│ ├── 192.168.1.100_pointcloud_20250325_143022.pcd
|
|
|
|
|
|
│ └── ...
|
|
|
|
|
|
├── 20250326/
|
|
|
|
|
|
│ └── ...
|
|
|
|
|
|
└── 20250327/
|
|
|
|
|
|
└── ...
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 路径组成部分详解
|
|
|
|
|
|
|
|
|
|
|
|
| 组成部分 | 说明 | 示例值 |
|
|
|
|
|
|
|---------|------|--------|
|
|
|
|
|
|
| basePath | 基础保存路径 | `D:/output` |
|
|
|
|
|
|
| 日期 | 拍摄日期(yyyyMMdd) | `20250325` |
|
|
|
|
|
|
| 类型 | 文件类型文件夹 | `amplitude`、`rgb`、`depth`、`depthColor`、`pointCloud` |
|
|
|
|
|
|
| SN | 相机序列号 | `192.168.1.100` |
|
|
|
|
|
|
| type | 文件类型(文件名中) | `amplitude`、`rgb`、`depth`、`depthColor`、`pointcloud` |
|
|
|
|
|
|
| timestamp | 时间戳(yyyyMMdd_HHmmss) | `20250325_143022` |
|
|
|
|
|
|
| ext | 文件扩展名 | `.png`、`.pcd` |
|
|
|
|
|
|
|
|
|
|
|
|
## 修改的文件
|
|
|
|
|
|
|
|
|
|
|
|
### 1. `LxCameraServiceImpl.java`
|
|
|
|
|
|
- ✅ 添加日期生成逻辑
|
|
|
|
|
|
- ✅ 修改所有文件保存路径,增加日期和类型文件夹
|
|
|
|
|
|
- ✅ 更新日志信息
|
|
|
|
|
|
|
|
|
|
|
|
**修改位置:**
|
|
|
|
|
|
- 第259行:添加日期生成
|
|
|
|
|
|
- 第291-350行:修改所有保存路径
|
|
|
|
|
|
|
|
|
|
|
|
### 2. `LX_CAMERA_USAGE.md`
|
|
|
|
|
|
- ✅ 添加路径格式说明
|
|
|
|
|
|
- ✅ 更新目录树示例
|
|
|
|
|
|
- ✅ 更新API响应示例
|
|
|
|
|
|
|
|
|
|
|
|
### 3. `LxCameraServiceExample.java`
|
|
|
|
|
|
- ✅ 更新示例注释
|
|
|
|
|
|
- ✅ 修正示例4的裁剪路径逻辑
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 新增文件
|
|
|
|
|
|
- ✅ `PATH_STRUCTURE.md` - 详细的路径结构说明文档
|
|
|
|
|
|
|
|
|
|
|
|
## 优势
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 更好的数据组织
|
|
|
|
|
|
- **按日期分类**:便于按天管理和查找数据
|
|
|
|
|
|
- **按类型分类**:便于按类型批量处理
|
|
|
|
|
|
- **结构清晰**:一目了然,易于维护
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 更高效的数据管理
|
|
|
|
|
|
- **快速定位**:可以快速找到某天某类型的所有数据
|
|
|
|
|
|
- **批量操作**:便于批量删除、备份、归档某天的数据
|
|
|
|
|
|
- **空间管理**:可以按天统计磁盘占用
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 更好的可扩展性
|
|
|
|
|
|
- **自动归档**:可以轻松实现按天、月、年归档
|
|
|
|
|
|
- **分布式存储**:可以将不同日期的数据存储在不同磁盘
|
|
|
|
|
|
- **数据清理**:便于实现定期清理旧数据的策略
|
|
|
|
|
|
|
|
|
|
|
|
## 兼容性说明
|
|
|
|
|
|
|
|
|
|
|
|
### 向后兼容
|
|
|
|
|
|
- ✅ API接口保持不变
|
|
|
|
|
|
- ✅ 参数格式保持不变
|
|
|
|
|
|
- ✅ 返回值结构保持不变
|
|
|
|
|
|
|
|
|
|
|
|
### 变更影响
|
|
|
|
|
|
- ⚠️ 调用方需要适配新的返回路径格式
|
|
|
|
|
|
- ⚠️ 现有的路径处理逻辑需要更新
|
|
|
|
|
|
|
|
|
|
|
|
## 迁移指南
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 更新调用代码
|
|
|
|
|
|
|
|
|
|
|
|
如果代码中硬编码了路径格式,需要更新:
|
|
|
|
|
|
|
|
|
|
|
|
**旧代码:**
|
|
|
|
|
|
```java
|
|
|
|
|
|
String pointCloudPath = basePath + "/" + cameraSn + "_pointcloud_" + timestamp + ".pcd";
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**新代码:**
|
|
|
|
|
|
```java
|
|
|
|
|
|
CaptureResult result = lxCameraService.capture(cameraSn, basePath);
|
|
|
|
|
|
String pointCloudPath = result.getFilePath("pointCloud");
|
|
|
|
|
|
// 路径格式: basePath/20250325/pointCloud/192.168.1.100_pointcloud_20250325_143022.pcd
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 处理历史数据
|
|
|
|
|
|
|
|
|
|
|
|
如果需要将旧格式数据迁移到新格式:
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
import java.nio.file.*;
|
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
|
|
|
|
|
|
|
public class DataMigration {
|
|
|
|
|
|
|
|
|
|
|
|
// 旧路径: basePath/SN_type_timestamp.ext
|
|
|
|
|
|
// 新路径: basePath/日期/类型/SN_type_timestamp.ext
|
|
|
|
|
|
|
|
|
|
|
|
public static void migrateOldData(String basePath) throws IOException {
|
|
|
|
|
|
Path baseDir = Paths.get(basePath);
|
|
|
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
|
|
|
|
|
|
|
|
|
|
|
|
Files.list(baseDir)
|
|
|
|
|
|
.filter(path -> !Files.isDirectory(path))
|
|
|
|
|
|
.forEach(file -> {
|
|
|
|
|
|
String filename = file.getFileName().toString();
|
|
|
|
|
|
|
|
|
|
|
|
// 解析文件名: 192.168.1.100_pointcloud_20250325_143022.pcd
|
|
|
|
|
|
String[] parts = filename.split("_");
|
|
|
|
|
|
if (parts.length >= 3) {
|
|
|
|
|
|
String sn = parts[0];
|
|
|
|
|
|
String type = parts[1];
|
|
|
|
|
|
String timestamp = parts[2].split("\\.")[0];
|
|
|
|
|
|
|
|
|
|
|
|
// 提取日期
|
|
|
|
|
|
String date = timestamp.substring(0, 8);
|
|
|
|
|
|
|
|
|
|
|
|
// 构建新路径
|
|
|
|
|
|
Path targetDir = baseDir.resolve(date).resolve(type);
|
|
|
|
|
|
try {
|
|
|
|
|
|
Files.createDirectories(targetDir);
|
|
|
|
|
|
Path targetFile = targetDir.resolve(filename);
|
|
|
|
|
|
Files.move(file, targetFile);
|
|
|
|
|
|
System.out.println("迁移: " + file + " -> " + targetFile);
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
|
System.err.println("迁移失败: " + filename);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) throws IOException {
|
|
|
|
|
|
migrateOldData("D:/output");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 更新数据清理逻辑
|
|
|
|
|
|
|
|
|
|
|
|
如果实现了定期清理旧数据的逻辑,需要适配新结构:
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
|
|
|
|
|
|
|
public class DataCleaner {
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除指定天数之前的所有数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static void cleanOldData(String basePath, int daysToKeep) {
|
|
|
|
|
|
LocalDate cutoffDate = LocalDate.now().minusDays(daysToKeep);
|
|
|
|
|
|
File baseDir = new File(basePath);
|
|
|
|
|
|
|
|
|
|
|
|
File[] dateDirs = baseDir.listFiles(File::isDirectory);
|
|
|
|
|
|
if (dateDirs == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
|
|
|
|
|
|
|
|
|
|
for (File dateDir : dateDirs) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
LocalDate dirDate = LocalDate.parse(dateDir.getName(), formatter);
|
|
|
|
|
|
if (dirDate.isBefore(cutoffDate)) {
|
|
|
|
|
|
deleteDirectory(dateDir);
|
|
|
|
|
|
System.out.println("已删除: " + dateDir.getAbsolutePath());
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
System.err.println("无法解析日期: " + dateDir.getName());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void deleteDirectory(File dir) {
|
|
|
|
|
|
File[] files = dir.listFiles();
|
|
|
|
|
|
if (files != null) {
|
|
|
|
|
|
for (File file : files) {
|
|
|
|
|
|
if (file.isDirectory()) {
|
|
|
|
|
|
deleteDirectory(file);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
file.delete();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
dir.delete();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
|
// 保留30天的数据
|
|
|
|
|
|
cleanOldData("D:/output", 30);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 测试建议
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 单元测试
|
|
|
|
|
|
```java
|
|
|
|
|
|
@Test
|
|
|
|
|
|
public void testPathFormat() {
|
|
|
|
|
|
String cameraSn = "192.168.1.100";
|
|
|
|
|
|
String basePath = "D:/output";
|
|
|
|
|
|
|
|
|
|
|
|
CaptureConfig config = CaptureConfig.createDefault();
|
|
|
|
|
|
CaptureResult result = lxCameraService.capture(cameraSn, basePath, config);
|
|
|
|
|
|
|
|
|
|
|
|
assertTrue(result.isSuccess());
|
|
|
|
|
|
|
|
|
|
|
|
String pointCloudPath = result.getFilePath("pointCloud");
|
|
|
|
|
|
assertTrue(pointCloudPath.contains("/20"));
|
|
|
|
|
|
assertTrue(pointCloudPath.contains("/pointCloud/"));
|
|
|
|
|
|
assertTrue(pointCloudPath.contains(cameraSn));
|
|
|
|
|
|
assertTrue(pointCloudPath.endsWith(".pcd"));
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 集成测试
|
|
|
|
|
|
```java
|
|
|
|
|
|
@Test
|
|
|
|
|
|
public void testDirectoryStructure() {
|
|
|
|
|
|
String basePath = "D:/test_output";
|
|
|
|
|
|
|
|
|
|
|
|
CaptureConfig config = CaptureConfig.createFullCapture();
|
|
|
|
|
|
CaptureResult result = lxCameraService.capture("192.168.1.100", basePath, config);
|
|
|
|
|
|
|
|
|
|
|
|
assertTrue(result.isSuccess());
|
|
|
|
|
|
|
|
|
|
|
|
// 验证目录结构
|
|
|
|
|
|
Files.walk(Paths.get(basePath))
|
|
|
|
|
|
.filter(Files::isDirectory)
|
|
|
|
|
|
.forEach(dir -> {
|
|
|
|
|
|
String dirName = dir.getFileName().toString();
|
|
|
|
|
|
assertTrue(dirName.matches("\\d{8}") || // 日期
|
|
|
|
|
|
dirName.equals("amplitude") ||
|
|
|
|
|
|
dirName.equals("rgb") ||
|
|
|
|
|
|
dirName.equals("depth") ||
|
|
|
|
|
|
dirName.equals("depthColor") ||
|
|
|
|
|
|
dirName.equals("pointCloud"));
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 注意事项
|
|
|
|
|
|
|
|
|
|
|
|
1. **自动创建目录**:系统会自动创建所需的目录结构
|
|
|
|
|
|
2. **路径长度限制**:Windows路径长度限制为260字符,注意basePath不要过长
|
|
|
|
|
|
3. **磁盘权限**:确保程序对basePath有读写权限
|
|
|
|
|
|
4. **并发安全**:多个相机同时拍照时,路径结构支持并发
|
|
|
|
|
|
5. **时区问题**:使用系统时区,注意时间的一致性
|
|
|
|
|
|
|
|
|
|
|
|
## 后续优化建议
|
|
|
|
|
|
|
|
|
|
|
|
1. **配置化**:将路径格式提取到配置文件,便于修改
|
|
|
|
|
|
2. **自定义模板**:支持用户自定义路径模板
|
|
|
|
|
|
3. **文件压缩**:自动压缩旧的点云数据
|
|
|
|
|
|
4. **分布式存储**:支持将不同日期数据存储到不同磁盘
|
|
|
|
|
|
5. **自动归档**:按月自动归档数据
|
|
|
|
|
|
|
|
|
|
|
|
## 相关文档
|
|
|
|
|
|
|
|
|
|
|
|
- `PATH_STRUCTURE.md` - 详细的路径结构说明
|
|
|
|
|
|
- `LX_CAMERA_USAGE.md` - 使用说明文档
|
|
|
|
|
|
- `CHANGELOG.md` - 变更日志
|