data-importer/src/main/java/org/example/IaShzhVsurfaceDataImporter2...

864 lines
34 KiB
Java
Raw Normal View History

2025-10-29 15:31:28 +08:00
package org.example;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* ---------Excel
*/
public class IaShzhVsurfaceDataImporter2 {
// 纵断面主表插入SQL
private static final String INSERT_VSURFACE_SQL =
"INSERT INTO SHZH_JCSJ.IA_M_VSURFACE " +
"(ZECD, ADCD, CHANNEL, ADDRESS, ISCTOWN, BASEELE, BASELGTD, BASELTTD, ELETYPE, " +
"METHOD, SIGNER, AUDID, STATUS, REMARK, MODITIME, ISENABLE, IMPORTYEAR, AUDBATCH, " +
"CADCD, GUID, INPUTTYPE, WSCD, SURFACE_CLASSIFY, OBJECT_NAME) " +
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
// 纵断面点表插入SQL
private static final String INSERT_VSPOINT_SQL =
"INSERT INTO SHZH_JCSJ.IA_M_VSPOINT " +
"(ZSURFACEID, TRANSECTNAME, FID, POINT, DISTANCE, DIRECTION, HDEELE, SMEELE, " +
"LGTD, LTTD, MODITIME, REMARK, GUID, CHANNEL) " +
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
// 检查纵断面主表重复的SQL
private static final String CHECK_VSURFACE_DUPLICATE_SQL =
"SELECT COUNT(*) FROM SHZH_JCSJ.IA_M_VSURFACE WHERE ZECD = ? and SURFACE_CLASSIFY = ?";
// 检查纵断面点表重复的SQL
private static final String CHECK_VSPOINT_DUPLICATE_SQL =
"SELECT COUNT(*) FROM SHZH_JCSJ.IA_M_VSPOINT WHERE ZSURFACEID = ? AND FID = ?";
public static void main(String[] args) {
// 测试用的固定路径
// args = new String[]{"C:\\Users\\gsiot\\Desktop\\项目资料\\山洪\\小流域\\111"};
// args = new String[]{"F:\\1111-湖工大50条成果-已通过初检-待入库"};
// args = new String[]{"F:\\3333-2024年度咸宁市8条20251017-已通过初检-待入库"};
// args = new String[]{"F:\\4444-长江科学院-黄冈28条-已通过初检-已统一表头-待入库"};
args = new String[]{"C:\\Users\\gsiot\\Desktop\\项目资料\\山洪\\小流域\\111"};
if (args.length == 0) {
System.out.println("请提供湖工大9.29目录路径作为参数");
return;
}
String baseDir = args[0];
File baseDirectory = new File(baseDir);
if (!baseDirectory.exists() || !baseDirectory.isDirectory()) {
System.out.println("指定的目录不存在或不是有效目录: " + baseDir);
return;
}
System.out.println("开始处理目录: " + baseDir);
try {
processAllCounties(baseDirectory);
} catch (Exception e) {
System.err.println("处理过程中发生错误: " + e.getMessage());
e.printStackTrace();
}
}
private static void processAllCounties(File baseDir) {
File[] countyDirs = baseDir.listFiles(File::isDirectory);
if (countyDirs == null) {
System.out.println("在基础目录下未找到任何县市文件夹");
return;
}
int totalProcessed = 0;
int totalSuccess = 0;
int totalDuplicates = 0;
int totalPointDuplicates = 0;
System.out.println("找到 " + countyDirs.length + " 个县市文件夹");
for (File countyDir : countyDirs) {
String countyName = extractCountyName(countyDir.getName());
System.out.println("\n=== 处理县市: " + countyName + " ===");
try {
ProcessResult result = processCountyData(countyDir, countyName);
totalProcessed += result.processed;
totalDuplicates += result.duplicates;
totalPointDuplicates += result.pointDuplicates;
totalSuccess++;
System.out.println("✓ 成功处理 " + countyName +
",导入 " + result.processed + " 条记录,跳过 " + result.duplicates +
" 条重复记录,断面点跳过 " + result.pointDuplicates + " 条重复记录");
} catch (Exception e) {
System.err.println("✗ 处理县市 " + countyName + " 时出错: " + e.getMessage());
}
}
System.out.println("\n=== 处理完成 ===");
System.out.println("成功处理县市: " + totalSuccess + " 个");
System.out.println("总导入记录: " + totalProcessed + " 条");
System.out.println("纵断面主表跳过重复记录: " + totalDuplicates + " 条");
System.out.println("纵断面点表跳过重复记录: " + totalPointDuplicates + " 条");
}
private static ProcessResult processCountyData(File countyDir, String countyName) throws Exception {
int totalProcessed = 0;
int totalDuplicates = 0;
int totalPointDuplicates = 0;
// 查找小流域目录
File watershedDir = findWatershedDirectory(countyDir);
if (watershedDir == null) {
System.out.println("在 " + countyName + " 下未找到小流域目录");
return new ProcessResult(0, 0, 0);
}
System.out.println("找到小流域目录: " + watershedDir.getName());
// 查找所有水系目录
File[] sxDirs = findSxDirectories(watershedDir);
if (sxDirs == null || sxDirs.length == 0) {
System.out.println("在 " + watershedDir.getPath() + " 下未找到水系目录");
return new ProcessResult(0, 0, 0);
}
System.out.println("找到 " + sxDirs.length + " 个水系文件夹:");
for (File sxDir : sxDirs) {
System.out.println(" - " + sxDir.getName());
}
// 遍历处理每个水系文件夹
for (File sxDir : sxDirs) {
System.out.println("\n处理水系: " + sxDir.getName());
ProcessResult result = processSxData(sxDir, countyName);
totalProcessed += result.processed;
totalDuplicates += result.duplicates;
totalPointDuplicates += result.pointDuplicates;
System.out.println("水系 " + sxDir.getName() + " 导入 " + result.processed + " 条记录,跳过 " +
result.duplicates + " 条重复记录,断面点跳过 " + result.pointDuplicates + " 条重复记录");
}
return new ProcessResult(totalProcessed, totalDuplicates, totalPointDuplicates);
}
private static ProcessResult processSxData(File sxDir, String countyName) throws Exception {
int processedCount = 0;
int duplicateCount = 0;
int pointDuplicateCount = 0;
// 按照新的目录结构查找文件
File crossSectionDir = findCrossSectionDirectory(sxDir);
if (crossSectionDir == null) {
System.out.println("在 " + sxDir.getPath() + " 下未找到纵断面成果表目录");
return new ProcessResult(0, 0, 0);
}
System.out.println("找到纵断面成果表目录: " + crossSectionDir.getPath());
// 查找所有Excel文件
File[] excelFiles = findExcelFiles(crossSectionDir);
if (excelFiles == null || excelFiles.length == 0) {
System.out.println("在 " + crossSectionDir.getPath() + " 下未找到纵断面Excel文件");
return new ProcessResult(0, 0, 0);
}
System.out.println("找到 " + excelFiles.length + " 个纵断面Excel文件:");
for (File excelFile : excelFiles) {
System.out.println(" - " + excelFile.getName());
}
// 提取流域编码
String watershedCode = CommonUtils.extractWatershedCode(sxDir.getName());
System.out.println("流域编码: " + watershedCode);
// 处理每个Excel文件
for (File excelFile : excelFiles) {
System.out.println("\n处理文件: " + excelFile.getName());
try {
// 验证文件是否为有效Excel文件
if (!isValidExcelFile(excelFile)) {
System.err.println("跳过无效的Excel文件: " + excelFile.getName());
continue;
}
ProcessResult result = readExcelAndImport(excelFile, countyName, watershedCode);
processedCount += result.processed;
duplicateCount += result.duplicates;
pointDuplicateCount += result.pointDuplicates;
System.out.println("文件 " + excelFile.getName() + " 导入 " + result.processed +
" 条记录,跳过 " + result.duplicates + " 条重复记录");
} catch (Exception e) {
System.err.println("处理文件 " + excelFile.getName() + " 时出错: " + e.getMessage());
if (e.getMessage().contains("valid OOXML")) {
System.err.println(" 文件可能损坏或格式不正确,跳过此文件");
}
// 继续处理下一个文件
}
}
return new ProcessResult(processedCount, duplicateCount, pointDuplicateCount);
}
/**
* Excel
*/
private static boolean isValidExcelFile(File file) {
if (!file.exists() || !file.isFile()) {
return false;
}
// 检查文件扩展名
String fileName = file.getName().toLowerCase();
if (!fileName.endsWith(".xlsx")) {
System.err.println("文件扩展名不是.xlsx: " + file.getName());
return false;
}
// 检查文件大小
if (file.length() == 0) {
System.err.println("文件大小为0: " + file.getName());
return false;
}
// 尝试打开文件验证格式
try (FileInputStream fis = new FileInputStream(file)) {
// 只读取文件头进行验证,不加载整个文件
byte[] header = new byte[4];
if (fis.read(header) != 4) {
return false;
}
// Excel文件的文件头特征
if (header[0] != 0x50 || header[1] != 0x4B || header[2] != 0x03 || header[3] != 0x04) {
System.err.println("文件头不符合Excel格式: " + file.getName());
return false;
}
return true;
} catch (Exception e) {
System.err.println("验证Excel文件失败: " + file.getName() + " - " + e.getMessage());
return false;
}
}
private static ProcessResult readExcelAndImport(File excelFile, String countyName, String wscd) throws Exception {
int importedCount = 0;
int duplicateCount = 0;
int pointDuplicateCount = 0;
// 先读取所有数据到内存
List<Object[]> vsurfaceDataList = new ArrayList<>();
List<Object[]> vspointDataList = new ArrayList<>();
readExcelData(wscd, excelFile, vsurfaceDataList, vspointDataList);
if (vsurfaceDataList.isEmpty()) {
System.out.println("未读取到有效数据");
return new ProcessResult(0, 0, 0);
}
System.out.println("成功读取 " + vsurfaceDataList.size() + " 条纵断面数据,包含 " +
vspointDataList.size() + " 个断面点,开始导入数据库...");
// 批量导入数据库
ProcessResult result = batchInsertData(vsurfaceDataList, vspointDataList);
return result;
}
private static void readExcelData(String wscd, File excelFile,
List<Object[]> vsurfaceDataList,
List<Object[]> vspointDataList) throws Exception {
// 保存原始设置
double originalRatio = ZipSecureFile.getMinInflateRatio();
try {
// 临时调整安全阈值
ZipSecureFile.setMinInflateRatio(0.001);
try (FileInputStream fis = new FileInputStream(excelFile);
Workbook workbook = new XSSFWorkbook(fis)) {
String surfaceClassify=excelFile.getName();
Pattern pattern = Pattern.compile("^[a-zA-Z0-9]+");
Matcher matcher = pattern.matcher(surfaceClassify);
if(matcher.find()){
surfaceClassify=matcher.group();
}else{
System.out.println("工作表表名有问题: " + surfaceClassify);
}
// 遍历所有工作表
for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
Sheet sheet = workbook.getSheetAt(sheetIndex);
String sheetName = sheet.getSheetName();
// 跳过填表说明等非数据工作表
if (sheetName.contains("填表说明") || sheetName.contains("说明")) {
continue;
}
System.out.println("处理工作表: " + sheetName);
try {
// 解析纵断面主表数据
Object[] vsurfaceData = parseVsurfaceData(sheet, sheetName, wscd, surfaceClassify);
if (vsurfaceData != null) {
vsurfaceDataList.add(vsurfaceData);
System.out.println("✓ 解析纵断面主表数据成功: " + sheetName);
// 解析断面点数据
List<Object[]> points = parseVspointData(sheet, (String) vsurfaceData[19]);
vspointDataList.addAll(points);
System.out.println("✓ 解析 " + points.size() + " 个断面点数据");
}
} catch (Exception e) {
System.err.println("解析工作表 " + sheetName + " 时出错: " + e.getMessage());
}
}
}
} finally {
// 恢复原始设置
ZipSecureFile.setMinInflateRatio(originalRatio);
}
}
private static Object[] parseVsurfaceData(Sheet sheet, String sheetName, String wscd, String surfaceClassify) {
try {
Object[] data = new Object[24]; // 对应24个插入参数
int index = 0;
// 根据Excel格式解析数据
// 第1行C列-所在位置
String location = getCellValue(sheet, 0, 2); // C1单元格
// 第2行C列-所在沟道G列-行政区划代码
String channel = getCellValue(sheet, 1, 2); // C2单元格
String adminCode = getCellValue(sheet, 1, 6); // G2单元格
// 第3行C列-是否跨县
String isCrossCounty = getCellValue(sheet, 2, 2); // C3单元格
// 第4行C列-控制点纬度G列-控制点高程
String baseLatitude = getCellValue(sheet, 3, 2); // C4单元格 - 控制点纬度
String baseElevation = getCellValue(sheet, 3, 6); // G4单元格 - 控制点高程
// 第5行C列-高程系G列-测量方法
String elevationType = getCellValue(sheet, 4, 2); // C5单元格 - 高程系
String method = getCellValue(sheet, 4, 6); // G5单元格 - 测量方法
// 控制点经度在Excel中没有明确位置设为空
String baseLongitude = null;
// 1. ZECD - 纵断面编码 (工作表名)
data[index++] = sheetName;
// 2. ADCD - 行政区划代码
data[index++] = getSafeString(adminCode);
// 3. CHANNEL - 所在沟道
data[index++] = getSafeString(channel);
// 4. ADDRESS - 所在位置
data[index++] = getSafeString(location);
// 5. ISCTOWN - 是否跨县
data[index++] = getSafeString(isCrossCounty);
// 6. BASEELE - 控制点高程
data[index++] = getSafeString(baseElevation);
// 7. BASELGTD - 控制点经度
data[index++] = getSafeString(baseLongitude);
// 8. BASELTTD - 控制点纬度
data[index++] = getSafeString(baseLatitude);
// 9. ELETYPE - 高程系
data[index++] = getSafeString(elevationType);
// 10. METHOD - 测量方法
data[index++] = getSafeString(method);
// 11. SIGNER - 填写人姓名(默认为空)
data[index++] = null;
// 12. AUDID - 审核批次号(默认为空)
data[index++] = null;
// 13. STATUS - 状态默认1-待审核)
data[index++] = "1";
// 14. REMARK - 备注
data[index++] = null;
// 15. MODITIME - 时间戳
data[index++] = new Timestamp(System.currentTimeMillis());
// 16. ISENABLE - 启用状态
data[index++] = "1";
// 17. IMPORTYEAR - 导入年份
data[index++] = "2025";
// 18. AUDBATCH - 审核批次
data[index++] = "BATCH_" + System.currentTimeMillis();
// 19. CADCD - 县级编码(从行政区划代码提取)
data[index++] = adminCode != null && adminCode.length() >= 6 ?
adminCode.substring(0, 6)+"000000000" : "";
// 20. GUID - 唯一标识
String guid = UUID.randomUUID().toString();
data[index++] = guid;
// 21. INPUTTYPE - 录入方式
data[index++] = "1";
// 22. WSCD - 流域编码
data[index++] = wscd;
// 23. SURFACE_CLASSIFY - 断面分类
data[index++] = surfaceClassify;
// 24. OBJECT_NAME - 对象名称(使用沟道名称)
data[index++] = null;
return data;
} catch (Exception e) {
System.err.println("解析纵断面主表数据失败: " + e.getMessage());
e.printStackTrace();
return null;
}
}
private static List<Object[]> parseVspointData(Sheet sheet, String vsurfaceId) {
List<Object[]> points = new ArrayList<>();
try {
// 找到数据开始行从第7行开始序号列开始
int startRow = 6; // 根据Excel格式数据从第7行开始
System.out.println("断面点数据从第 " + (startRow + 1) + " 行开始");
for (int i = startRow; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
// 检查序号列是否为空
Cell serialCell = row.getCell(0);
if (serialCell == null || isCellEmpty(serialCell)) {
continue;
}
Object[] pointData = parseVspointRowData(row, vsurfaceId, i - startRow + 1);
if (pointData != null) {
points.add(pointData);
}
}
} catch (Exception e) {
System.err.println("解析断面点数据失败: " + e.getMessage());
e.printStackTrace();
}
return points;
}
private static Object[] parseVspointRowData(Row row, String vsurfaceId, int fid) {
try {
Object[] data = new Object[14]; // 对应14个插入参数
int index = 0;
// 1. ZSURFACEID - 纵断面主表ID
data[index++] = vsurfaceId;
// 2. TRANSECTNAME - 断面名称(使用测量点)
String measurePoint = getCellStringValue(row.getCell(1));
data[index++] = getSafeString(measurePoint);
// 3. FID - 断面序号
data[index++] = fid;
// 4. POINT - 断面信息-测量点
data[index++] = getSafeString(measurePoint);
// 5. DISTANCE - 断面信息-距离(m) - 第3列
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(2)));
// 6. DIRECTION - 量距方向(°) - 第4列
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(3)));
// 7. HDEELE - 断面信息-河底高程(m) - 第5列
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(4)));
// 8. SMEELE - 断面信息-水面高程(m) - 第6列
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(5)));
// 9. LGTD - 经度(°) - 第7列
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(6)));
// 10. LTTD - 纬度(°) - 第8列
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(7)));
// 11. MODITIME - 时间戳
data[index++] = new Timestamp(System.currentTimeMillis());
// 12. REMARK - 备注
data[index++] = null;
// 13. GUID - 唯一标识
data[index++] = UUID.randomUUID().toString();
// 14. CHANNEL - 量距方向(°) - 使用第4列的值
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(3)));
return data;
} catch (Exception e) {
System.err.println("解析断面点行数据失败: " + e.getMessage());
return null;
}
}
private static ProcessResult batchInsertData(List<Object[]> vsurfaceDataList, List<Object[]> vspointDataList) {
int importedCount = 0;
int duplicateCount = 0;
int pointDuplicateCount = 0;
Connection conn = null;
PreparedStatement vsurfacePstmt = null;
PreparedStatement vspointPstmt = null;
PreparedStatement checkVsurfaceDupPstmt = null;
PreparedStatement checkVspointDupPstmt = null;
try {
conn = DatabaseUtil.getConnection();
if (conn == null) {
System.err.println("无法获取数据库连接");
return new ProcessResult(0, 0, 0);
}
vsurfacePstmt = conn.prepareStatement(INSERT_VSURFACE_SQL);
vspointPstmt = conn.prepareStatement(INSERT_VSPOINT_SQL);
checkVsurfaceDupPstmt = conn.prepareStatement(CHECK_VSURFACE_DUPLICATE_SQL);
checkVspointDupPstmt = conn.prepareStatement(CHECK_VSPOINT_DUPLICATE_SQL);
conn.setAutoCommit(false); // 开启事务
// 处理纵断面主表数据
for (Object[] rowData : vsurfaceDataList) {
try {
String zecd = (String) rowData[0];
String surface_clasify = (String) rowData[22];
// 检查纵断面是否重复
checkVsurfaceDupPstmt.setString(1, zecd);
checkVsurfaceDupPstmt.setString(2, surface_clasify);
try (ResultSet rs = checkVsurfaceDupPstmt.executeQuery()) {
if (rs.next() && rs.getInt(1) > 0) {
duplicateCount++;
System.out.println("跳过重复纵断面: " + zecd);
continue;
}
}
// 插入数据 - 设置所有参数
setVsurfaceParameters(vsurfacePstmt, rowData);
vsurfacePstmt.executeUpdate();
importedCount++;
System.out.println("✓ 插入纵断面记录: " + zecd);
} catch (Exception e) {
System.err.println("纵断面数据插入失败: " + e.getMessage());
e.printStackTrace();
}
}
// 处理纵断面点表数据
int pointImportedCount = 0;
for (Object[] pointData : vspointDataList) {
try {
String vsurfaceId = (String) pointData[0];
Integer fid = (Integer) pointData[2];
// 检查断面点是否重复
checkVspointDupPstmt.setString(1, vsurfaceId);
checkVspointDupPstmt.setInt(2, fid);
try (ResultSet rs = checkVspointDupPstmt.executeQuery()) {
if (rs.next() && rs.getInt(1) > 0) {
pointDuplicateCount++;
continue;
}
}
// 插入数据 - 设置所有参数
setVspointParameters(vspointPstmt, pointData);
vspointPstmt.addBatch();
pointImportedCount++;
// 每10条执行一次批量插入
if (pointImportedCount % 10 == 0) {
vspointPstmt.executeBatch();
vspointPstmt.clearBatch(); // 清空批量
System.out.println("已批量插入 " + pointImportedCount + " 条断面点记录");
}
} catch (Exception e) {
System.err.println("断面点数据插入失败: " + e.getMessage());
e.printStackTrace();
}
}
// 执行剩余的断面点批量插入
if (pointImportedCount > 0) {
vspointPstmt.executeBatch();
System.out.println("最终批量插入完成,共 " + pointImportedCount + " 条断面点记录");
}
conn.commit(); // 提交事务
System.out.println("事务提交成功");
} catch (Exception e) {
System.err.println("批量插入数据失败: " + e.getMessage());
e.printStackTrace();
if (conn != null) {
try {
conn.rollback();
System.out.println("事务回滚成功");
} catch (Exception rollbackEx) {
System.err.println("事务回滚失败: " + rollbackEx.getMessage());
}
}
} finally {
// 关闭资源
closeResource(checkVspointDupPstmt);
closeResource(checkVsurfaceDupPstmt);
closeResource(vspointPstmt);
closeResource(vsurfacePstmt);
closeResource(conn);
}
return new ProcessResult(importedCount, duplicateCount, pointDuplicateCount);
}
// 设置纵断面主表参数
private static void setVsurfaceParameters(PreparedStatement pstmt, Object[] rowData) throws Exception {
for (int i = 0; i < rowData.length; i++) {
Object value = rowData[i];
if (value == null) {
pstmt.setNull(i + 1, java.sql.Types.NULL);
} else if (value instanceof String) {
pstmt.setString(i + 1, (String) value);
} else if (value instanceof Double) {
pstmt.setDouble(i + 1, (Double) value);
} else if (value instanceof Integer) {
pstmt.setInt(i + 1, (Integer) value);
} else if (value instanceof Timestamp) {
pstmt.setTimestamp(i + 1, (Timestamp) value);
} else {
pstmt.setObject(i + 1, value);
}
}
}
// 设置纵断面点表参数
private static void setVspointParameters(PreparedStatement pstmt, Object[] pointData) throws Exception {
for (int i = 0; i < pointData.length; i++) {
Object value = pointData[i];
if (value == null) {
pstmt.setNull(i + 1, java.sql.Types.NULL);
} else if (value instanceof String) {
pstmt.setString(i + 1, (String) value);
} else if (value instanceof Double) {
pstmt.setDouble(i + 1, (Double) value);
} else if (value instanceof Integer) {
pstmt.setInt(i + 1, (Integer) value);
} else if (value instanceof Timestamp) {
pstmt.setTimestamp(i + 1, (Timestamp) value);
} else {
pstmt.setObject(i + 1, value);
}
}
}
// 安全关闭资源的方法
private static void closeResource(AutoCloseable resource) {
if (resource != null) {
try {
resource.close();
} catch (Exception e) {
System.err.println("关闭资源时出错: " + e.getMessage());
}
}
}
// 辅助方法安全获取字符串避免null
private static String getSafeString(String value) {
return value != null ? value : "";
}
// 辅助方法解析Double提供默认值
private static Double parseDoubleWithDefault(String value) {
if (value != null && !value.trim().isEmpty()) {
try {
return Double.parseDouble(value.trim());
} catch (NumberFormatException e) {
return 0.0;
}
}
return 0.0;
}
// 辅助方法
private static class ProcessResult {
int processed;
int duplicates;
int pointDuplicates;
ProcessResult(int processed, int duplicates, int pointDuplicates) {
this.processed = processed;
this.duplicates = duplicates;
this.pointDuplicates = pointDuplicates;
}
}
// 目录查找方法(保持不变)
private static File findWatershedDirectory(File countyDir) {
File[] subDirs = countyDir.listFiles(File::isDirectory);
if (subDirs != null) {
for (File subDir : subDirs) {
if (subDir.getName().contains("小流域")) {
return subDir;
}
}
if (subDirs.length > 0) return subDirs[0];
}
return null;
}
private static File[] findSxDirectories(File watershedDir) {
File[] subDirs = watershedDir.listFiles(File::isDirectory);
if (subDirs != null) {
List<File> sxDirs = new ArrayList<>();
for (File subDir : subDirs) {
if (subDir.getName().contains("水系") || subDir.getName().matches("^HBWFF.*")) {
sxDirs.add(subDir);
}
}
return sxDirs.toArray(new File[0]);
}
return null;
}
private static File findCrossSectionDirectory(File sxDir) {
// 按照新目录结构:水系目录 > 电子数据 > 测量数据 > 防治对象断面成果 > 纵断面成果表
File electronicDataDir = findSubDirectory(sxDir, "电子数据");
if (electronicDataDir == null) {
System.out.println("在 " + sxDir.getPath() + " 下未找到电子数据目录");
return null;
}
File measureDataDir = findSubDirectory(electronicDataDir, "测量数据");
if (measureDataDir == null) {
System.out.println("在 " + electronicDataDir.getPath() + " 下未找到测量数据目录");
return null;
}
File sectionResultDir = findSubDirectory(measureDataDir, "防治对象断面成果");
if (sectionResultDir == null) {
System.out.println("在 " + measureDataDir.getPath() + " 下未找到防治对象断面成果目录");
return null;
}
File crossSectionDir = findSubDirectory(sectionResultDir, "纵断面成果表");
if (crossSectionDir == null) {
System.out.println("在 " + sectionResultDir.getPath() + " 下未找到纵断面成果表目录");
return null;
}
return crossSectionDir;
}
private static File findSubDirectory(File parentDir, String dirName) {
File[] subDirs = parentDir.listFiles(File::isDirectory);
if (subDirs != null) {
for (File subDir : subDirs) {
if (subDir.getName().equals(dirName)) {
return subDir;
}
}
// 如果没有精确匹配,尝试包含匹配
for (File subDir : subDirs) {
if (subDir.getName().contains(dirName)) {
return subDir;
}
}
}
return null;
}
private static File[] findExcelFiles(File crossSectionDir) {
File[] files = crossSectionDir.listFiles((dir, name) ->
name.toLowerCase().endsWith(".xlsx"));
return files != null ? files : new File[0];
}
private static String extractCountyName(String dirName) {
return dirName.contains("、") ? dirName.split("、")[1].trim() : dirName;
}
private static String getCellValue(Sheet sheet, int rowNum, int colNum) {
Row row = sheet.getRow(rowNum);
if (row != null) {
Cell cell = row.getCell(colNum);
return getCellStringValue(cell);
}
return null;
}
private static String getCellStringValue(Cell cell) {
if (cell == null) return null;
try {
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue().trim();
case NUMERIC:
double num = cell.getNumericCellValue();
return (num == (long) num) ? String.valueOf((long) num) : String.valueOf(num);
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
default:
return null;
}
} catch (Exception e) {
return null;
}
}
private static boolean isCellEmpty(Cell cell) {
if (cell == null) return true;
switch (cell.getCellType()) {
case BLANK:
return true;
case STRING:
return cell.getStringCellValue().trim().isEmpty();
default:
return false;
}
}
}