# 路径格式更新说明 ## 更新日期 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` - 变更日志