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

864 lines
34 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}
}