王波 il y a 4 semaines
commit
b9024a245f

+ 130 - 0
pom.xml

@@ -0,0 +1,130 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.example</groupId>
+  <artifactId>DataAcquisitionPlus</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <name>Archetype - DataAcquisitionPlus</name>
+  <url>http://maven.apache.org</url>
+
+  <description>Spring Boot basic project without database</description>
+
+  <parent>
+    <groupId>org.springframework.boot</groupId>
+    <artifactId>spring-boot-starter-parent</artifactId>
+    <version>2.7.10</version> <!-- 可根据需要修改版本 -->
+    <relativePath/> <!-- 查找父项目路径 -->
+  </parent>
+
+  <properties>
+    <java.version>1.8</java.version> <!-- 可改为11或21等 -->
+  </properties>
+
+  <dependencies>
+    <!-- Spring Boot 核心 Web 模块,用于创建 RESTful 接口 -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+    </dependency>
+
+
+    <!-- 其他依赖项 -->
+    <dependency>
+      <groupId>com.alibaba</groupId>
+      <artifactId>easyexcel</artifactId>
+      <version>3.1.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.alibaba</groupId>
+      <artifactId>fastjson</artifactId>
+      <version>2.0.40</version>
+    </dependency>
+
+    <dependency>
+      <groupId>io.swagger</groupId>
+      <artifactId>swagger-annotations</artifactId>
+      <version>1.6.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <version>1.16.20</version>
+      <scope>provided</scope> <!-- 如果在编译时生成代码,但在运行时不需要 -->
+    </dependency>
+
+    <dependency>
+      <groupId>org.xerial</groupId>
+      <artifactId>sqlite-jdbc</artifactId>
+      <version>3.39.3.0</version>
+    </dependency>
+    <!-- JSON.org 的 JSON 库 -->
+    <dependency>
+      <groupId>org.json</groupId>
+      <artifactId>json</artifactId>
+      <version>20231013</version> <!-- 请根据需要选择版本 -->
+    </dependency>
+
+    <dependency>
+      <groupId>io.swagger</groupId>
+      <artifactId>swagger-annotations</artifactId>
+      <version>1.6.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+      <version>2.15.2</version>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springdoc</groupId>
+      <artifactId>springdoc-openapi-ui</artifactId>
+      <version>1.7.0</version> <!-- 请确保使用最新版本 -->
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>4.5.13</version> <!-- 使用最新版本 -->
+    </dependency>
+
+
+
+    <!-- Spring Boot 默认使用 SLF4J + Logback,无需额外添加 -->
+    <!-- 如果是非 Spring Boot 项目,可显式添加以下依赖 -->
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.7.36</version>
+    </dependency>
+
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <version>1.2.11</version>
+    </dependency>
+
+    <!-- Spring Boot 测试模块(可选) -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!-- Spring Boot Maven 插件 -->
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

+ 85 - 0
src/main/java/com/acquisition/Controller/DataAcquisitionController.java

@@ -0,0 +1,85 @@
+package com.acquisition.Controller;
+
+import com.acquisition.service.DataAcquisition.FileProcessorConfigService;
+import com.acquisition.service.DataAcquisition.FileProcessorService;
+import com.acquisition.service.DataAcquisition.FilesdataCopy;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 前端控制器
+ * </p>
+ *
+ * @author wang
+ * @since 2025-01-07
+ */
+@RestController
+@RequestMapping("/data-acquisition")
+public class DataAcquisitionController {
+
+    @Autowired
+    private FileProcessorService fileProcessorService;
+
+    @Autowired
+    private FileProcessorConfigService configService;
+
+    @Autowired
+    private FilesdataCopy filesdataCopy;
+
+
+
+    /**
+     * 创建data文件并复制demo文件
+     *
+     * @return 完成信息
+     * @throws Exception 如果处理文件时出现错误
+     */
+    @GetMapping("/fileprocess")
+    @Operation(summary = "创建data文件并复制demo文件", description = "执行创建data文件并复制demo文件")
+    @ApiResponse(responseCode = "200", description = "成功返回完成信息",
+            content = @Content(mediaType = "text/plain",
+                    schema = @Schema(implementation = String.class)))
+    public String fileprocess() throws Exception {
+        fileProcessorService.processFiles();
+        return "文件夹创建已完成";
+    }
+
+    /**
+     * 数据自动采集
+     *
+     * @return 完成信息
+     * @throws Exception 如果处理文件时出现错误
+     */
+    @GetMapping("/fileprocessconfig")
+    @Operation(summary = "数据自动采集配置", description = "数据自动采集配置")
+    @ApiResponse(responseCode = "200", description = "成功返回完成信息",
+            content = @Content(mediaType = "text/plain",
+                    schema = @Schema(implementation = String.class)))
+    public String fileprocessconfig() throws Exception {
+        configService.processFiles();
+        return "数据自动配置已完成";
+    }
+
+    /**
+     * 104转发协议测点
+     *
+     * @return 完成信息
+     * @throws Exception 如果处理文件时出现错误
+     */
+    @GetMapping("/copyfiledata")
+    @Operation(summary = "104转发协议测点配置", description = "104转发协议测点配置")
+    @ApiResponse(responseCode = "200", description = "成功返回完成信息",
+            content = @Content(mediaType = "text/plain",
+                    schema = @Schema(implementation = String.class)))
+    public String filecopydata() throws Exception {
+        filesdataCopy.processFiles();
+        return "104转发协议测点配置完成";
+    }
+}

+ 94 - 0
src/main/java/com/acquisition/DataAcquisitionApplication.java

@@ -0,0 +1,94 @@
+package com.acquisition;
+
+
+import com.acquisition.config.HttpRequestSender;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.system.ApplicationHome;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.Environment;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Scanner;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@SpringBootApplication
+
+public class DataAcquisitionApplication {
+
+    private static final Logger log = LoggerFactory.getLogger(DataAcquisitionApplication.class);
+    public static void main(String[] args) throws UnknownHostException {
+        System.out.println("DataAcquisition 程序启动...");
+
+        ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(DataAcquisitionApplication.class, args);
+
+        Environment env = configurableApplicationContext.getEnvironment();
+        String ip = InetAddress.getLocalHost().getHostAddress();
+        String port = env.getProperty("server.port");
+        String path = env.getProperty("server.servlet.context-path");
+        ApplicationHome home = new ApplicationHome(DataAcquisitionApplication.class);
+        String filePath = home.getSource().getParentFile().getAbsolutePath();
+
+        //        createFolder();
+
+        log.info("\n-------------------------------------------------------------------\n\t" +
+                "经济运行系统启动成功,访问路径如下:\n\t" +
+                "本地路径: \t\thttp://localhost:" + port + path + "\n\t" +
+                "网络地址: \t\thttp://" + ip + ":" + port + path + "\n\t" +
+                "API文档: \t\thttp://" + ip + ":" + port + path + "/swagger-ui.html\n" +
+                "-----------------------------------------------------------------------");
+        log.info(filePath);
+        System.out.println("Hello World!");
+
+        Scanner scanner = new Scanner(System.in);
+
+        while (true) {
+            System.out.println("请选择要执行的操作:");
+            System.out.println("1. 开始生成data文件夹");
+            System.out.println("2. 开始修改配置");
+            System.out.println("3. 开始修改104转发协议测点");
+            System.out.println("4. 退出程序——直接叉掉");
+
+            System.out.print("请输入选项(1/2/3/4):");
+            String choice = scanner.nextLine();
+
+            switch (choice) {
+                case "1":
+                    try {
+                        String firstResponse = HttpRequestSender.sendGetRequest("http://localhost:8080/data-acquisition/fileprocess");
+                        System.out.println("开始生成data文件夹:" + firstResponse);
+                    } catch (Exception e) {
+                        System.err.println("生成data文件夹失败:" + e.getMessage());
+                    }
+                    break;
+                case "2":
+                    try {
+                        String secondResponse = HttpRequestSender.sendGetRequest("http://localhost:8080/data-acquisition/fileprocessconfig");
+                        System.out.println("开始修改配置:" + secondResponse);
+                    } catch (Exception e) {
+                        System.err.println("修改配置失败:" + e.getMessage());
+                    }
+                    break;
+                case "3":
+                    try {
+                        String secondResponse = HttpRequestSender.sendGetRequest("http://localhost:8080/data-acquisition/copyfiledata");
+                        System.out.println("开始修改配置:" + secondResponse);
+                    } catch (Exception e) {
+                        System.err.println("修改配置失败:" + e.getMessage());
+                    }
+                    break;
+                case "4":
+                    System.out.println("程序退出。");
+                    scanner.close();
+                    return;
+                default:
+                    System.out.println("无效的选项,请重新选择。");
+            }
+        }
+    }
+
+}

+ 96 - 0
src/main/java/com/acquisition/config/FileUtils.java

@@ -0,0 +1,96 @@
+package com.acquisition.config;
+
+
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.List;
+
+public class FileUtils {
+
+    // 读取 Excel 中指定列的数据
+
+    public static List<String> readExcelColumn(String excelPath, int columnIndex) throws Exception {
+        List<String> columnData = new ArrayList<>();
+
+        try (FileInputStream fis = new FileInputStream(excelPath);
+             Workbook workbook = new XSSFWorkbook(fis)) {
+            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表
+            int firstRow = sheet.getFirstRowNum();
+            int lastRow = sheet.getLastRowNum();
+
+            for (int i = firstRow; i <= lastRow; i++) {
+                Row row = sheet.getRow(i);
+                String cellValue = "";
+                if(row != null){
+                    Cell cell = row.getCell(columnIndex);
+                    cellValue =  getCellValueAsString(cell);
+                }
+                columnData.add(cellValue);
+            }
+        }
+        return columnData;
+    }
+
+    private static String getCellValueAsString(Cell cell) {
+        if (cell == null || cell.getCellType() == CellType.BLANK) {
+            return "无";
+        }
+
+        switch (cell.getCellType()) {
+            case STRING:
+                return cell.getStringCellValue().trim();
+            case NUMERIC:
+                if (DateUtil.isCellDateFormatted(cell)) {
+                    return cell.getDateCellValue().toString().trim();
+                }else{
+                    return String.valueOf(cell.getNumericCellValue()).trim();
+                }
+            case BOOLEAN:
+                return String.valueOf(cell.getBooleanCellValue()).trim();
+            case FORMULA:
+                return cell.getCellFormula().trim();
+            default:
+                return cell.toString().trim();
+        }
+    }
+    public static void createDirectory(String directoryPath) throws IOException {
+        Path path = Paths.get(directoryPath);
+        if (!Files.exists(path)) {
+            Files.createDirectories(path);
+        }
+    }
+
+    public static void copyFolderContent(String sourceDir, String targetDir) throws IOException {
+        Path sourcePath = Paths.get(sourceDir);
+        Path targetPath = Paths.get(targetDir);
+
+        if (!Files.exists(sourcePath) || !Files.isDirectory(sourcePath)) {
+            System.err.println("源目录不存在或不是目录: " + sourceDir);
+            return; // 源目录不存在或不是目录,则直接返回
+        }
+
+        Files.walk(sourcePath).forEach(source -> {
+                    Path target = targetPath.resolve(sourcePath.relativize(source));
+                    try {
+                        if (Files.isDirectory(source)) {
+                            if(!Files.exists(target)){
+                                Files.createDirectories(target);
+                            }
+                        } else {
+                            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+                        }
+                    }catch (IOException ex){
+                        System.err.println("拷贝文件失败, 源文件: " + source + ", 目标文件: " + target + " " + ex.getMessage());
+                    }
+                }
+        );
+    }
+}

+ 47 - 0
src/main/java/com/acquisition/config/HttpRequestSender.java

@@ -0,0 +1,47 @@
+package com.acquisition.config;
+
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+public class HttpRequestSender {
+
+    // 发送 GET 请求
+    public static String sendGetRequest(String url) throws Exception {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        HttpGet httpGet = new HttpGet(url);
+
+        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
+            if (response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
+                return EntityUtils.toString(response.getEntity());
+            } else {
+                throw new Exception("HTTP 请求失败,状态码:" + response.getStatusLine().getStatusCode());
+            }
+        } finally {
+            httpClient.close();
+        }
+    }
+
+    // 发送 POST 请求
+    public static String sendPostRequest(String url, String data) throws Exception {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        HttpPost httpPost = new HttpPost(url);
+        httpPost.setHeader("Content-Type", "text/plain");  // 假设是文本数据
+        httpPost.setEntity(new StringEntity(data));
+
+        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+            if (response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
+                return EntityUtils.toString(response.getEntity());
+            } else {
+                throw new Exception("HTTP 请求失败,状态码:" + response.getStatusLine().getStatusCode());
+            }
+        } finally {
+            httpClient.close();
+        }
+    }
+}

+ 39 - 0
src/main/java/com/acquisition/config/InlineArrayObjPrettyPrinter.java

@@ -0,0 +1,39 @@
+package com.acquisition.config;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.util.DefaultIndenter;
+import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+
+import java.io.IOException;
+
+public class InlineArrayObjPrettyPrinter extends DefaultPrettyPrinter {
+
+    private static final long serialVersionUID = 1L;
+
+    // 根对象缩进:两空格 + 换行
+    private static final Indenter ROOT_OBJECT_INDENTER =
+            new DefaultIndenter("  ", DefaultIndenter.SYS_LF);
+
+    // 数组中的对象缩进:不换行
+    private static final Indenter INLINE_OBJECT_INDENTER =
+            NopIndenter.instance;
+
+    public InlineArrayObjPrettyPrinter() {
+        super();
+        this.indentArraysWith(new DefaultIndenter("  ", DefaultIndenter.SYS_LF));
+    }
+
+    @Override
+    public DefaultPrettyPrinter createInstance() {
+        return new InlineArrayObjPrettyPrinter();
+    }
+
+    @Override
+    public void writeStartObject(JsonGenerator g) throws IOException {
+        this._objectIndenter = (_nesting == 0)
+                ? ROOT_OBJECT_INDENTER     // 根对象换行
+                : INLINE_OBJECT_INDENTER;  // 数组中的对象不换行
+        super.writeStartObject(g);
+    }
+}
+

+ 819 - 0
src/main/java/com/acquisition/service/DataAcquisition/FileProcessorConfigService.java

@@ -0,0 +1,819 @@
+package com.acquisition.service.DataAcquisition;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.sql.*;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class FileProcessorConfigService {
+
+    private final String collectionServiceDir;
+
+    // 构造方法中初始化路径
+    public FileProcessorConfigService() {
+        this.collectionServiceDir = System.getProperty("user.home") + "\\Desktop\\CollectionService";
+    }
+
+    /**
+     * 处理数据文件
+     *
+     * @throws Exception 如果处理文件时出现错误
+     */
+
+    public void processFiles() throws Exception {
+        // 读取配置Excel文件
+        List<List<String>> configData = configreadConfigExcel(collectionServiceDir + "\\demo\\config.xlsx");
+
+        // 从第1行开始遍历配置数据,i从0开始
+        for (int i = 1; i < configData.size(); i++) {  // i从0开始
+
+            List<String> rowData = configData.get(i); // 当前行数据
+            String folderNamecj = rowData.get(6); // 第一行第6列数据
+            String folderNamezf = rowData.get(14); // 第一行第14列数据
+            String folderNameredis = rowData.get(20); // 第一行第20列数据
+            String folderNamefs = rowData.get(22); // 第一行第22列数据
+            String folderNamejs = rowData.get(25); // 第一行第25列数据
+
+            String dataFolderPathcj = collectionServiceDir + "\\data" + (i) + "\\" + folderNamecj; // data1, data2, ...
+            String dataFolderPathzf = collectionServiceDir + "\\data" + (i) + "\\" + folderNamezf;
+            String dataFolderPathredis = collectionServiceDir + "\\data" + (i) + "\\" + folderNameredis;
+            String dataFolderPathfs = collectionServiceDir + "\\data" + (i) + "\\" + folderNamefs;
+            String dataFolderPathjs = collectionServiceDir + "\\data" + (i) + "\\" + folderNamejs;
+
+            // 获取该行对应的配置总表路径
+//            String configExcelPath = collectionServiceDir + "\\data" + (i) + "\\配置总表.xlsx";
+            String configExcelPath = collectionServiceDir + "\\data" + (i) + "\\" + folderNamecj + ".xlsx";
+
+            // 1. 读取配置总表.xlsx中的数据并生成sqlite3文件
+            List<List<Object>> configExcelData = readConfigExcel(configExcelPath);
+
+            // 获取并传递需要的列数据给generateKeyTableFile方法
+            // 处理采集第2列到第10列的数据
+            if (!folderNamecj.equals("无")) {
+                cjmodifyJsonConfigFile(dataFolderPathcj, "wormholed.json", folderNamecj, rowData.get(28)); // 修改json文件,使用第28列数据作为插件
+                JsonpluginFile(dataFolderPathcj, rowData.get(28) + ".json", rowData.get(7), rowData.get(9), rowData.get(13), rowData.get(11));
+                System.out.println("正在生成 data" + (i) + "采集 sqlite文件");
+                generateKeyTableFile(dataFolderPathcj, configExcelData, 2, 10); // 读取第2列到第10列数据
+            }
+            //处理转发第11列到第19列的数据
+            if (!folderNamezf.equals("无")) {
+                modifyJsonConfigFile(dataFolderPathzf, "wormholed.json", folderNamezf); // 修改json文件
+                zfJsonpluginFile(dataFolderPathzf, null, rowData.get(15), rowData.get(16), rowData.get(17));
+                System.out.println("正在生成 data" + (i) + "转发 sqlite文件");
+                generateKeyTableFile(dataFolderPathzf, configExcelData, 11, 19); // 读取第11列到第19列数据
+            }
+            //处理redis第20列到第24列的数据
+            if (!folderNameredis.equals("无")) {
+                modifyJsonConfigFile(dataFolderPathredis, "wormholed.json", folderNameredis); // 修改json文件,修改pwd为第14列
+                redisJsonpluginFile(dataFolderPathredis, rowData.get(19), rowData.get(27));
+                System.out.println("正在生成 data" + (i) + "redis sqlite文件");
+                generateKeyTableFile(dataFolderPathredis, configExcelData, 20, 24); // 读取20列到第24列的数据
+            }
+            //处理发送第25列到第29列的数据
+            if (!folderNamefs.equals("无")) {
+                modifyJsonConfigFile(dataFolderPathfs, "wormholed.json", folderNamefs); // 修改json文件,修改pwd为第14列
+                fsJsonpluginFile(dataFolderPathfs, rowData.get(23), rowData.get(24));
+                System.out.println("正在生成 data" + (i) + "发送 sqlite文件");
+                generateKeyTableFile(dataFolderPathfs, configExcelData, 25, 29); // 读取第25列到第29列的数据
+            }
+            //处理接收第30列到第34列的数据
+            if (!folderNamejs.equals("无")) {
+                modifyJsonConfigFile(dataFolderPathjs, "wormholed.json", folderNamejs); // 修改json文件,修改pwd为第14列
+                jsJsonpluginFile(dataFolderPathjs, rowData.get(26));
+                System.out.println("正在生成 data" + (i) + "接收 sqlite文件");
+                generateKeyTableFile(dataFolderPathjs, configExcelData, 30, 34); // 读取第30列到第34列的数据
+            }
+
+        }
+    }
+
+
+    //读取Excel文件中的数据
+    public List<List<String>> configreadConfigExcel(String excelPath) throws Exception {
+        List<List<String>> data = new ArrayList<>();
+
+        try (FileInputStream fis = new FileInputStream(excelPath);
+             Workbook workbook = new XSSFWorkbook(fis)) {
+            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表
+            int maxColumn = getMaxColumnCount(sheet);  // 获取最大列数
+
+            for (Row row : sheet) {
+                List<String> rowData = new ArrayList<>();
+                if (row != null) {  // 添加非空检查
+                    for (int i = 0; i < maxColumn; i++) {
+                        Cell cell = row.getCell(i);
+                        String cellValue = getCellValueAsString(cell);
+                        rowData.add(cellValue);
+                    }
+                } else {
+                    for (int i = 0; i < maxColumn; i++) {
+                        rowData.add("无");
+                    }
+                }
+
+                data.add(rowData);
+            }
+        }
+        return data;
+    }
+
+    // 获取最大列数
+    private int getMaxColumnCount(Sheet sheet) {
+        int maxColumn = 0;
+        for (Row row : sheet) {
+            if (row != null) {
+                maxColumn = Math.max(maxColumn, row.getLastCellNum());
+            }
+        }
+        return maxColumn;
+    }
+
+
+    //Excel读取数据类型判断
+    private String getCellValueAsString(Cell cell) {
+        if (cell == null || cell.getCellType() == CellType.BLANK) {
+            return "无";
+        }
+
+        switch (cell.getCellType()) {
+            case STRING:
+                return cell.getStringCellValue().trim();
+            case NUMERIC:
+                if (DateUtil.isCellDateFormatted(cell)) {
+                    return cell.getDateCellValue().toString().trim();
+                } else {
+                    return String.valueOf(cell.getNumericCellValue()).trim();
+                }
+            case BOOLEAN:
+                return String.valueOf(cell.getBooleanCellValue()).trim();
+            case FORMULA:
+                return cell.getCellFormula().trim();
+            default:
+                return cell.toString().trim();
+        }
+    }
+
+    //读取Excel文件
+//    /**
+//     * 不保留原始数据类型
+//     */
+//    public List<List<String>> readConfigExcel(String excelPath) throws Exception {
+//        List<List<String>> data = new ArrayList<>();
+//
+//        // 通过 FileInputStream 读取 Excel 文件
+//        try (FileInputStream fis = new FileInputStream(excelPath);
+//             Workbook workbook = new XSSFWorkbook(fis)) {
+//
+//            // 获取第一个工作表
+//            Sheet sheet = workbook.getSheetAt(0);
+//
+//            // 遍历每一行
+//            for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {  // 采用getPhysicalNumberOfRows来提高效率
+//                Row row = sheet.getRow(i);
+//
+//                if (row == null) continue;  // 跳过空行
+//
+//                List<String> rowData = new ArrayList<>();
+//
+//                // 遍历每个单元格
+//                for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {  // 采用getPhysicalNumberOfCells来提高效率
+//                    Cell cell = row.getCell(j);
+//                    if (cell == null) {
+//                        rowData.add("");  // 如果单元格为空,添加空字符串
+//                    } else {
+//                        switch (cell.getCellType()) {
+//                            case STRING:
+//                                rowData.add(cell.getStringCellValue().trim());
+//                                break;
+//                            case NUMERIC:
+//                                rowData.add(String.valueOf(cell.getNumericCellValue()).trim());
+//                                break;
+//                            case BOOLEAN:
+//                                rowData.add(String.valueOf(cell.getBooleanCellValue()).trim());
+//                                break;
+//                            default:
+//                                rowData.add("");  // 对于其他类型的单元格返回空字符串
+//                        }
+//                    }
+//                }
+//
+//                // 将读取到的行数据添加到数据列表中
+//                data.add(rowData);
+//            }
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//            throw new Exception("Error reading Excel file: " + e.getMessage());
+//        }
+//
+//        return data;
+//    }
+
+
+    /**
+     * 保留原始类型
+     * @param excelPath
+     * @return
+     * @throws Exception
+     */
+
+    public List<List<Object>> readConfigExcel(String excelPath) throws Exception {
+        List<List<Object>> data = new ArrayList<>();
+
+        try (FileInputStream fis = new FileInputStream(excelPath);
+             Workbook workbook = new XSSFWorkbook(fis)) {
+
+            Sheet sheet = workbook.getSheetAt(0);
+            DataFormatter formatter = new DataFormatter(); // 用于获取用户看到的格式化值
+
+            for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
+                Row row = sheet.getRow(i);
+                if (row == null) continue;
+
+                List<Object> rowData = new ArrayList<>();
+
+                for (int j = 0; j < row.getLastCellNum(); j++) {
+                    Cell cell = row.getCell(j);
+                    if (cell == null) {
+                        rowData.add(null);
+                        continue;
+                    }
+
+                    switch (cell.getCellType()) {
+                        case STRING:
+                            rowData.add(cell.getStringCellValue().trim());
+                            break;
+                        case NUMERIC:
+                            if (DateUtil.isCellDateFormatted(cell)) {
+                                rowData.add(cell.getDateCellValue());
+                            } else {
+                                double numeric = cell.getNumericCellValue();
+                                String formatted = formatter.formatCellValue(cell);
+                                if (formatted.matches("-?\\d+")) {
+                                    // 格式化后没有小数点,说明用户原本输入的是整数
+                                    rowData.add((long) numeric);
+                                } else {
+                                    rowData.add(numeric);
+                                }
+                            }
+                            break;
+                        case BOOLEAN:
+                            rowData.add(cell.getBooleanCellValue());
+                            break;
+                        case FORMULA:
+                            try {
+                                switch (cell.getCachedFormulaResultType()) {
+                                    case NUMERIC:
+                                        if (DateUtil.isCellDateFormatted(cell)) {
+                                            rowData.add(cell.getDateCellValue());
+                                        } else {
+                                            double result = cell.getNumericCellValue();
+                                            String formatted = formatter.formatCellValue(cell);
+                                            if (formatted.matches("-?\\d+")) {
+                                                rowData.add((long) result);
+                                            } else {
+                                                rowData.add(result);
+                                            }
+                                        }
+                                        break;
+                                    case STRING:
+                                        rowData.add(cell.getStringCellValue().trim());
+                                        break;
+                                    case BOOLEAN:
+                                        rowData.add(cell.getBooleanCellValue());
+                                        break;
+                                    default:
+                                        rowData.add(null);
+                                }
+                            } catch (Exception e) {
+                                rowData.add(null);
+                            }
+                            break;
+                        case BLANK:
+                            rowData.add(null);
+                            break;
+                        default:
+                            rowData.add(null);
+                    }
+                }
+
+                data.add(rowData);
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new Exception("Error reading Excel file: " + e.getMessage());
+        }
+
+        return data;
+    }
+
+
+
+    // 生成keytable.sqlite3文件
+    private void generateKeyTableFile(String dataFolderPath, List<List<Object>> configExcelData, int startCol, int endCol) throws Exception {
+        // 提取指定列范围的数据
+        List<List<Object>> dataToWrite = new ArrayList<>();
+
+        // 从configExcelData中获取第startCol到endCol列的数据
+        for (List<Object> row : configExcelData) {
+            // 只取指定范围的列
+            List<Object> rowData = row.subList(startCol, endCol + 1); // 提取列范围的数据
+            dataToWrite.add(rowData);
+        }
+
+        // 根据提取的数据生成sqlite3文件
+        String keytableDir = dataFolderPath + "\\keytable";
+        File directory = new File(keytableDir);
+        if (directory.exists() && directory.isDirectory()) {
+            File[] files = directory.listFiles();
+            if (files != null) {
+                for (File file : files) {
+                    if (file.isFile()) {
+                        file.delete();
+                    }
+                }
+            }
+        }
+        File keytableDirFile = new File(keytableDir);
+        if (!keytableDirFile.exists()) {
+            keytableDirFile.mkdir(); // 创建 keytable 目录
+        }
+
+        String sqliteFilePath = keytableDir + "\\keytable.sqlite3";
+        // 写入SQLite数据库
+        writeToSQLite(dataToWrite, sqliteFilePath);
+    }
+
+
+    // 写入SQLite数据库
+//    /**
+//     * 读取配置Excel文件并返回数据列表
+//     *所有字段数据类型为整数
+//     * @return 数据列表
+//     * @throws Exception 读取文件时发生的异常
+//     */
+//    private void writeToSQLite(List<List<String>> data, String sqliteFilePath) {
+//        try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + sqliteFilePath)) {
+//            // 获取列名(假设第一行是列名)
+//            List<String> columnNames = data.get(0); // 第一行作为列名
+//
+//            // 创建表格
+//            String createTableSQL = "CREATE TABLE IF NOT EXISTS key_table (";
+//
+//            // 检查每列的数据类型
+//            for (int i = 0; i < columnNames.size(); i++) {
+//                String columnType = "TEXT"; // 默认列类型为 TEXT
+//
+//                // 遍历当前列的所有数据来检查是否包含数字
+//                for (int rowIdx = 1; rowIdx < data.size(); rowIdx++) { // 从第二行开始检查数据
+//                    String cellValue = data.get(rowIdx).get(i).trim();
+//                    // 如果列中任何数据是数字,将列的数据类型设置为 INTEGER
+//                    if (cellValue.matches("-?\\d+(\\.\\d+)?")) { // 允许整数或浮动数字
+//                        columnType = "INTEGER";
+//                        break;
+//                    }
+//                }
+//
+//                createTableSQL += columnNames.get(i) + " " + columnType; // 使用原始列名和类型
+//                if (i < columnNames.size() - 1) {
+//                    createTableSQL += ", ";
+//                }
+//            }
+//            createTableSQL += ");";
+//
+//            // 执行创建表格语句
+//            try (Statement stmt = conn.createStatement()) {
+//                stmt.execute(createTableSQL);
+//            }
+//
+//            // 插入数据
+//            StringBuilder insertSQL = new StringBuilder("INSERT INTO key_table VALUES (");
+//            for (int i = 0; i < columnNames.size() - 1; i++) {
+//                insertSQL.append("?, ");
+//            }
+//            insertSQL.append("?);"); // 最后一列不需要逗号
+//
+//            try (PreparedStatement pstmt = conn.prepareStatement(insertSQL.toString())) {
+//                for (int rowIdx = 1; rowIdx < data.size(); rowIdx++) { // 从第二行开始处理数据
+//                    List<String> row = data.get(rowIdx);
+//                    for (int colIdx = 0; colIdx < row.size(); colIdx++) {
+//                        String value = row.get(colIdx).trim();
+//
+//                        // 判断值是否为数字并设定相应的数据类型
+//                        if (value.matches("-?\\d+(\\.\\d+)?")) {
+//                            // 如果是浮动数字,转换为整数
+//                            try {
+//                                double numericValue = Double.parseDouble(value);
+//                                // 如果是浮动数字,四舍五入并转为整数
+//                                if (numericValue % 1 != 0) {
+//                                    pstmt.setInt(colIdx + 1, (int) Math.round(numericValue)); // 插入整数
+//                                } else {
+//                                    pstmt.setInt(colIdx + 1, (int) numericValue); // 插入整数
+//                                }
+//                            } catch (NumberFormatException e) {
+//                                pstmt.setString(colIdx + 1, value); // 如果无法解析为数字,插入为字符串
+//                            }
+//                        } else {
+//                            pstmt.setString(colIdx + 1, value); // 插入文本
+//                        }
+//                    }
+//                    pstmt.addBatch(); // 添加批处理
+//                }
+//                pstmt.executeBatch(); // 执行批量插入
+//            }
+//        } catch (SQLException e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+
+//    /**
+//     * 读取配置Excel文件并返回数据列表
+//     *指定字段数据类型
+//     * @return 数据列表
+//     * @throws Exception 读取文件时发生的异常
+//     */
+//    private void writeToSQLite(List<List<String>> data, String sqliteFilePath) {
+//        try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + sqliteFilePath)) {
+//            List<String> columnNames = data.get(0); // 第一行作为列名
+//
+//            // 创建表格(表名改为 key_table)
+//            String createTableSQL = "CREATE TABLE IF NOT EXISTS key_table (";
+//            for (int i = 0; i < columnNames.size(); i++) {
+//                String colName = columnNames.get(i);
+//                String columnType = "TEXT";
+//
+//                for (int rowIdx = 1; rowIdx < data.size(); rowIdx++) {
+//                    String cellValue = data.get(rowIdx).get(i).trim();
+//                    if (cellValue.matches("-?\\d+(\\.\\d+)?")) {
+//                        if (colName.endsWith("valid") ||colName.endsWith("addr")) {
+//                            columnType = "INTEGER";
+//                        } else {
+//                            columnType = "REAL";
+//                        }
+//                        break;
+//                    }
+//                }
+//
+//                createTableSQL += colName + " " + columnType;
+//                if (i < columnNames.size() - 1) {
+//                    createTableSQL += ", ";
+//                }
+//            }
+//            createTableSQL += ");";
+//
+//            try (Statement stmt = conn.createStatement()) {
+//                stmt.execute(createTableSQL);
+//            }
+//
+//            // 插入数据
+//            StringBuilder insertSQL = new StringBuilder("INSERT INTO key_table VALUES (");
+//            for (int i = 0; i < columnNames.size() - 1; i++) {
+//                insertSQL.append("?, ");
+//            }
+//            insertSQL.append("?);");
+//
+//            try (PreparedStatement pstmt = conn.prepareStatement(insertSQL.toString())) {
+//                for (int rowIdx = 1; rowIdx < data.size(); rowIdx++) {
+//                    List<String> row = data.get(rowIdx);
+//                    for (int colIdx = 0; colIdx < row.size(); colIdx++) {
+//                        String colName = columnNames.get(colIdx);
+//                        String value = row.get(colIdx).trim();
+//
+//                        if (value.matches("-?\\d+(\\.\\d+)?")) {
+//                            try {
+//                                double numericValue = Double.parseDouble(value);
+//
+//                                if (colName.endsWith("valid")) {
+//                                    pstmt.setInt(colIdx + 1, (int) Math.round(numericValue));
+//                                } else {
+//                                    double rounded = Math.round(numericValue * 10.0) / 10.0;
+//                                    pstmt.setDouble(colIdx + 1, rounded);
+//                                }
+//                            } catch (NumberFormatException e) {
+//                                pstmt.setString(colIdx + 1, value);
+//                            }
+//                        } else {
+//                            pstmt.setString(colIdx + 1, value);
+//                        }
+//                    }
+//                    pstmt.addBatch();
+//                }
+//                pstmt.executeBatch();
+//            }
+//        } catch (SQLException e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+
+    //    /**
+    //     * 读取配置Excel文件并返回数据列表
+    //     *自动判断字段数据类型
+    //     * @return 数据列表
+    //     * @throws Exception 读取文件时发生的异常
+    //     */
+    private void writeToSQLite(List<List<Object>> data, String sqliteFilePath) {
+        if (data == null || data.isEmpty()) return;
+
+        try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + sqliteFilePath)) {
+            List<Object> columnNamesRaw = data.get(0);
+            List<String> columnNames = new ArrayList<>();
+            for (Object obj : columnNamesRaw) {
+                columnNames.add(obj != null ? obj.toString().trim() : "col");
+            }
+
+            List<String> columnTypes = new ArrayList<>();
+
+            // 推断每列数据类型
+            for (int col = 0; col < columnNames.size(); col++) {
+                String type = "TEXT"; // 默认是文本
+
+                for (int row = 1; row < data.size(); row++) {
+                    if (col >= data.get(row).size()) continue;
+
+                    Object value = data.get(row).get(col);
+                    if (value == null) continue;
+
+                    if (value instanceof Integer || value instanceof Long) {
+                        type = "INTEGER";
+                    } else if (value instanceof Double || value instanceof Float) {
+                        type = "REAL";
+                    } else if (value instanceof Boolean) {
+                        type = "INTEGER"; // SQLite 没有 BOOLEAN 类型,用 INTEGER 表示 true/false
+                    } else if (value instanceof Date) {
+                        type = "TEXT"; // 或 "NUMERIC",取决于是否存时间戳
+                    } else {
+                        type = "TEXT";
+                        break; // 只要出现非数字,就默认整列是 TEXT
+                    }
+                }
+
+                columnTypes.add(type);
+            }
+
+            // 创建表
+            StringBuilder createTableSQL = new StringBuilder("CREATE TABLE IF NOT EXISTS key_table (");
+            for (int i = 0; i < columnNames.size(); i++) {
+                createTableSQL.append(columnNames.get(i)).append(" ").append(columnTypes.get(i));
+                if (i < columnNames.size() - 1) createTableSQL.append(", ");
+            }
+            createTableSQL.append(");");
+
+            try (Statement stmt = conn.createStatement()) {
+                stmt.execute(createTableSQL.toString());
+            }
+
+            // 插入数据
+            StringBuilder insertSQL = new StringBuilder("INSERT INTO key_table VALUES (");
+            for (int i = 0; i < columnNames.size(); i++) {
+                insertSQL.append("?");
+                if (i < columnNames.size() - 1) insertSQL.append(",");
+            }
+            insertSQL.append(");");
+
+            try (PreparedStatement pstmt = conn.prepareStatement(insertSQL.toString())) {
+                for (int rowIdx = 1; rowIdx < data.size(); rowIdx++) {
+                    List<Object> row = data.get(rowIdx);
+                    for (int colIdx = 0; colIdx < columnNames.size(); colIdx++) {
+                        Object value = colIdx < row.size() ? row.get(colIdx) : null;
+                        String type = columnTypes.get(colIdx);
+
+                        if (value == null) {
+                            pstmt.setNull(colIdx + 1, Types.NULL);
+                        } else if (type.equals("INTEGER")) {
+                            if (value instanceof Boolean) {
+                                pstmt.setInt(colIdx + 1, ((Boolean) value) ? 1 : 0);
+                            } else {
+                                pstmt.setInt(colIdx + 1, ((Number) value).intValue());
+                            }
+                        } else if (type.equals("REAL")) {
+                            pstmt.setDouble(colIdx + 1, ((Number) value).doubleValue());
+                        } else if (type.equals("TEXT")) {
+                            if (value instanceof Date) {
+                                pstmt.setString(colIdx + 1, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) value));
+                            } else {
+                                pstmt.setString(colIdx + 1, value.toString());
+                            }
+                        } else {
+                            pstmt.setObject(colIdx + 1, value);
+                        }
+                    }
+                    pstmt.addBatch();
+                }
+                pstmt.executeBatch();
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    // 修改采集wormholed.json文件
+    public void cjmodifyJsonConfigFile(String folderPath, String jsonFileName, String pwdData, String pluginData) throws IOException {
+
+        String jsonFilePath = folderPath + "/config/" + jsonFileName;
+        String content = new String(Files.readAllBytes(Paths.get(jsonFilePath)));
+
+        // 替换 "engine" 中的 "pwd" 字段
+        if (pwdData != null && !pwdData.equals("无")) {
+            content = content.replaceAll(
+                    "(?s)(\"engine\"\\s*:\\s*\\{.*?)(\"pwd\"\\s*:\\s*\")[^\"]*(\")",
+                    "$1$2/home/GYEE/service/" + pwdData + "$3"
+            );
+        }
+
+        // 替换 "ci" 中的 "plugin" 字段
+        if (pluginData != null && !pluginData.equals("无")) {
+            // plugin
+            content = content.replaceAll(
+                    "(?s)(\"ci\"\\s*:\\s*\\{.*?)(\"plugin\"\\s*:\\s*\")[^\"]*(\")",
+                    "$1$2" + pluginData + ".so$3"
+            );
+            // config
+            content = content.replaceAll(
+                    "(?s)(\"ci\"\\s*:\\s*\\{.*?)(\"config\"\\s*:\\s*\")[^\"]*(\")",
+                    "$1$2" + pluginData + ".json$3"
+            );
+        }
+
+        // 写回文件(内容结构完全保持不变)
+        Files.write(Paths.get(jsonFilePath), content.getBytes());
+
+    }
+
+
+    // 采集plugin.json文件目录
+    public void JsonpluginFile(String folderPath, String jsonFileName, String ipData, String portData, String gyfpip, String gyfpport) throws IOException {
+        //采集104或者modbusJSON地址
+        String jsonFilePath = folderPath + "/plugin/" + jsonFileName;
+        //采集gyfp文件地址
+        String gyfpFilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改采集第一个 JSON 文件
+        modifyJsonFile(mapper, jsonFilePath, ipData, portData, null);
+        // 读取并修改采集第二个 JSON 文件
+        modifyJsonFile(mapper, gyfpFilePath, gyfpip, gyfpport, null);
+
+        // 根据 jsonFileName 删除对应的文件
+        deleteFileByFileName(folderPath, jsonFileName);
+
+    }
+
+    // 转发plugin.json文件目录
+    public void zfJsonpluginFile(String folderPath, String ipData, String portData, String gyfpip, String gyfpport) throws IOException {
+
+        //转发gyfp文件地址
+        String zfFilePath = folderPath + "/plugin/" + "libplugingyfp.json";
+        //转发gyfp2文件地址
+        String zf2FilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改转发gyfp JSON 文件
+        modifyJsonFile(mapper, zfFilePath, ipData, portData, null);
+        // 读取并修改转发gyfp2 JSON 文件
+        modifyJsonFile(mapper, zf2FilePath, gyfpip, gyfpport, null);
+
+    }
+
+    // redis plugin.json文件目录
+    public void redisJsonpluginFile(String folderPath, String portData, String dbid) throws IOException {
+
+        //redis gyfp2文件地址
+        String redisFilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+        //redis-redis文件地址
+        String redis2FilePath = folderPath + "/plugin/" + "libpluginredis.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改redis gyfp JSON 文件
+        modifyJsonFile(mapper, redisFilePath, null, portData, null);
+        // 读取并修改redis redis JSON 文件
+        modifyJsonFile(mapper, redis2FilePath, null, null, dbid);
+
+    }
+
+    // 发送plugin.json文件目录
+    public void fsJsonpluginFile(String folderPath, String ipData, String portData) throws IOException {
+
+        //fs gyfp2文件地址
+        String fsFilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改fs gyfp2 JSON 文件
+        modifyJsonFile(mapper, fsFilePath, ipData, portData, null);
+
+    }
+
+    // 接收plugin.json文件目录
+    public void jsJsonpluginFile(String folderPath, String portData) throws IOException {
+
+        //js gyfp2文件地址
+        String fsFilePath = folderPath + "/plugin/" + "libplugingyfp2.json";
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+
+        // 读取并修改fs gyfp2 JSON 文件
+        modifyJsonFile(mapper, fsFilePath, null, portData, null);
+
+    }
+
+    private void modifyJsonFile(ObjectMapper mapper, String filePath, String ipData, String portData, String dbid) throws IOException {
+
+        String content = new String(Files.readAllBytes(Paths.get(filePath)));
+
+        // 修改 "ip"
+        if (ipData != null && !ipData.equals("无")) {
+            content = content.replaceAll("\"ip\"\\s*:\\s*\"[^\"]*\"", "\"ip\": \"" + ipData + "\"");
+        }
+
+        // 修改 "port"
+        if (portData != null && !portData.equals("无")) {
+            try {
+                int port = (int) Double.parseDouble(portData);
+                content = content.replaceAll("\"port\"\\s*:\\s*\\d+", "\"port\": " + port);
+            } catch (NumberFormatException e) {
+                System.err.println("端口转换失败:" + e.getMessage());
+            }
+        }
+
+        // 修改 "dbid"
+        if (dbid != null && !dbid.equals("无")) {
+//            content = content.replaceAll("\"dbid\"\\s*:\\s*\"[^\"]*\"", "\"dbid\": \"" + dbid + "\"");
+//            content = content.replaceAll("\"dbid\"\\s*:\\s*([^,\\}]+)", "\"dbid\": " + Integer.valueOf(dbid));
+            try {
+                int dbidInt = (int) Double.parseDouble(dbid);
+                content = content.replaceAll("\"dbid\"\\s*:\\s*([^,\\}]+)", "\"dbid\": " + dbidInt);
+            } catch (NumberFormatException e) {
+                System.err.println("dbid 转换失败: " + e.getMessage());
+                // 可选:使用默认值或跳过替换操作
+            }
+
+        }
+
+        // 写回原文件
+        Files.write(Paths.get(filePath), content.getBytes());
+    }
+
+    //采集有两种-执行删除plugin中json文件
+    private void deleteFileByFileName(String folderPath, String jsonFileName) {
+        Path filePathToDelete = null;
+        if ("libplugin104.json".equals(jsonFileName)) {
+            filePathToDelete = Paths.get(folderPath, "plugin", "libpluginmodbus.json");
+        } else {
+            filePathToDelete = Paths.get(folderPath, "plugin", "libplugin104.json");
+        }
+
+        try {
+            Files.delete(filePathToDelete);
+            System.out.println("成功删除文件:" + filePathToDelete);
+        } catch (NoSuchFileException e) {
+            System.err.println("文件不存在,删除失败:" + filePathToDelete + " " + e.getMessage());
+        } catch (IOException e) {
+            System.err.println("删除文件失败:" + filePathToDelete + " " + e.getMessage());
+        }
+    }
+
+    //修改除采集外其它四个目录wormholed文件
+    public void modifyJsonConfigFile(String folderPath, String jsonFileName, String pwdData) throws IOException {
+
+        String jsonFilePath = folderPath + "/config/" + jsonFileName;
+        String content = new String(Files.readAllBytes(Paths.get(jsonFilePath)));
+
+        // 替换 "engine" 区域内的 "pwd" 字段,只改值,格式保持原样
+        if (pwdData != null && !pwdData.equals("无")) {
+            content = content.replaceAll(
+                    "(?s)(\"engine\"\\s*:\\s*\\{.*?)(\"pwd\"\\s*:\\s*\")[^\"]*(\")",
+                    "$1$2/home/GYEE/service/" + pwdData + "$3"
+            );
+        }
+        // 写回文件,保持原样格式
+        Files.write(Paths.get(jsonFilePath), content.getBytes());
+    }
+
+}

+ 128 - 0
src/main/java/com/acquisition/service/DataAcquisition/FileProcessorService.java

@@ -0,0 +1,128 @@
+package com.acquisition.service.DataAcquisition;
+
+import com.acquisition.config.FileUtils;
+
+import com.alibaba.excel.util.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class FileProcessorService {
+
+    private final String collectionServiceDir;
+
+    public FileProcessorService() {
+        // 动态获取用户桌面的路径
+        this.collectionServiceDir = System.getProperty("user.home") + "/Desktop/CollectionService";
+    }
+
+
+    /**
+     * 创建data文件并复制demo文件
+     *
+     * @throws Exception
+     */
+    public void processFiles1() throws Exception {
+        String configExcelPath = collectionServiceDir + "/demo/config.xlsx";
+
+        // 各字段列索引
+        int[] columnIndexes = {6, 14, 20, 22, 25}; // 对应采集服务名、三区转发服务等
+
+        String[] sourceFolders = {
+                "gyee_syz_cj",
+                "gyee_syz_zf",
+                "gyee_syz_redis",
+                "gyee_syz_fs",
+                "gyee_syz_js"
+        };
+        Map<String, Boolean> copiedDirs = new HashMap<>();
+        // 读取每列数据并处理
+        for (int i = 0; i < columnIndexes.length; i++) {
+            List<String> folderNames = FileUtils.readExcelColumn(configExcelPath, columnIndexes[i]);
+
+            for (int j = 1; j < folderNames.size(); j++) {
+                String folderName = folderNames.get(j);
+                // 如果数据为空或为“无”,跳过当前行
+                if (StringUtils.isBlank(folderName) || "无".equals(folderName)) {
+                    continue;
+                }
+                String targetDir = collectionServiceDir + "/data" + (j) + "/" + folderName;
+                if (!copiedDirs.containsKey(targetDir)) {
+                    FileUtils.createDirectory(targetDir);
+                    String sourceDir = collectionServiceDir + "/demo/" + sourceFolders[i];
+                    FileUtils.copyFolderContent(sourceDir, targetDir);
+                    copiedDirs.put(targetDir, true);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 增加在 demo 目录中查找与 folderName 匹配的 Excel 文件
+     * @throws Exception
+     */
+    public void processFiles() throws Exception {
+        String configExcelPath = collectionServiceDir + "/demo/config.xlsx";
+
+        // 各字段列索引
+        int[] columnIndexes = {6, 14, 20, 22, 25}; // 对应采集服务名、三区转发服务等
+
+        String[] sourceFolders = {
+                "gyee_syz_cj",
+                "gyee_syz_zf",
+                "gyee_syz_redis",
+                "gyee_syz_fs",
+                "gyee_syz_js"
+        };
+        Map<String, Boolean> copiedDirs = new HashMap<>();
+
+        // 读取每列数据并处理
+        for (int i = 0; i < columnIndexes.length; i++) {
+            List<String> folderNames = FileUtils.readExcelColumn(configExcelPath, columnIndexes[i]);
+
+            for (int j = 1; j < folderNames.size(); j++) {
+                String folderName = folderNames.get(j);
+                // 如果数据为空或为“无”,跳过当前行
+                if (StringUtils.isBlank(folderName) || "无".equals(folderName)) {
+                    continue;
+                }
+
+                String targetBaseDir = collectionServiceDir + "/data" + j;
+                String targetDir = targetBaseDir + "/" + folderName;
+
+                if (!copiedDirs.containsKey(targetDir)) {
+                    // 创建目标目录
+                    FileUtils.createDirectory(targetDir);
+
+                    // 复制 demo 模板目录内容
+                    String sourceDir = collectionServiceDir + "/demo/" + sourceFolders[i];
+                    FileUtils.copyFolderContent(sourceDir, targetDir);
+                    copiedDirs.put(targetDir, true);
+                }
+
+                // 在 demo 目录中查找与 folderName 匹配的 Excel 文件
+                File demoDir = new File(collectionServiceDir + "/demo");
+                File[] matchingFiles = demoDir.listFiles((dir, name) ->
+                        name.toLowerCase().endsWith(".xlsx") && name.contains(folderName)
+                );
+
+                if (matchingFiles != null) {
+                    for (File excelFile : matchingFiles) {
+                        Path targetPath = Paths.get(targetBaseDir, excelFile.getName());
+                        Files.copy(excelFile.toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING);
+                    }
+                }
+            }
+        }
+    }
+
+}

+ 132 - 0
src/main/java/com/acquisition/service/DataAcquisition/FilesdataCopy.java

@@ -0,0 +1,132 @@
+package com.acquisition.service.DataAcquisition;
+
+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 org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class FilesdataCopy {
+
+    private final String collectionServiceDir;
+
+    public FilesdataCopy() {
+        this.collectionServiceDir = System.getProperty("user.home") + "/Desktop/CollectionService";
+    }
+
+    public void processFiles() throws Exception {
+        String inputPath = collectionServiceDir + "/demo/配置总表.xlsx";
+        String outputPath = collectionServiceDir + "/104转发协议测点.xlsx";
+
+        FileInputStream fis = new FileInputStream(new File(inputPath));
+        Workbook inputWorkbook = new XSSFWorkbook(fis);
+        Sheet inputSheet = inputWorkbook.getSheetAt(0);
+
+        Workbook outputWorkbook = new XSSFWorkbook();
+        Sheet outputSheet = outputWorkbook.createSheet("Sheet1");
+
+        // 写入表头
+        String[] headers = {"id", "测点", "测点类型", "公共地址", "104地址", "系数", "场站简称", "测点描述"};
+        Row headerRow = outputSheet.createRow(0);
+        for (int i = 0; i < headers.length; i++) {
+            headerRow.createCell(i).setCellValue(headers[i]);
+        }
+
+        List<String> mongoKeys = new ArrayList<>();
+        List<String> names = new ArrayList<>();
+
+        int mongoKeyCol = 19; // T列 (索引从0开始)
+        int nameCol = 0;      // 名称列 assumed to be 第1列
+
+        for (int i = 1; i <= inputSheet.getLastRowNum(); i++) {
+            Row row = inputSheet.getRow(i);
+            if (row == null) continue;
+
+            Cell mongoKeyCell = row.getCell(mongoKeyCol);
+            Cell nameCell = row.getCell(nameCol);
+
+            if (mongoKeyCell == null || nameCell == null) continue;
+
+            mongoKeys.add(mongoKeyCell.toString().trim());
+            names.add(nameCell.toString().trim());
+        }
+
+        int id = 1;
+        int ai104Addr = 16385, di104Addr = 1;
+        int aiPublicAddr = 1, diPublicAddr = 1;
+        int aiCount = 0, diCount = 0;
+
+        for (int i = 0; i < mongoKeys.size(); i++) {
+            String mongoKey = mongoKeys.get(i);
+            String name = names.get(i);
+
+            String pointType = "";
+            int lastUnderscoreIndex = mongoKey.lastIndexOf('_');
+            if (lastUnderscoreIndex != -1 && lastUnderscoreIndex < mongoKey.length() - 1) {
+                String suffix = mongoKey.substring(lastUnderscoreIndex + 1).toUpperCase();
+                if (suffix.startsWith("AI") || suffix.startsWith("PI")) {
+                    pointType = "AI";
+                } else if (suffix.startsWith("DI")) {
+                    pointType = "DI";
+                }
+            }
+
+
+            String pointTypeUpper = pointType.toUpperCase();
+
+            int current104Addr;
+            int currentPublicAddr;
+
+            if ("AI".equals(pointTypeUpper)) {
+                current104Addr = ai104Addr;
+                currentPublicAddr = aiPublicAddr;
+                ai104Addr++;
+                aiCount++;
+                if (ai104Addr > 24384) {
+                    ai104Addr = 16385;
+                    aiPublicAddr++;
+                }
+            } else if ("DI".equals(pointTypeUpper)) {
+                current104Addr = di104Addr;
+                currentPublicAddr = diPublicAddr;
+                di104Addr++;
+                diCount++;
+                if (di104Addr > 16000) {
+                    di104Addr = 1;
+                    diPublicAddr++;
+                }
+            } else {
+                continue; // 跳过无法识别类型的行
+            }
+
+            Row outputRow = outputSheet.createRow(id);
+            outputRow.createCell(0).setCellValue(id);                         // id
+            outputRow.createCell(1).setCellValue(mongoKey);                  // 测点
+            outputRow.createCell(2).setCellValue(pointTypeUpper);            // 测点类型
+            outputRow.createCell(3).setCellValue(currentPublicAddr);         // 公共地址
+            outputRow.createCell(4).setCellValue(current104Addr);            // 104地址
+            outputRow.createCell(5).setCellValue(1);                         // 系数
+            outputRow.createCell(6).setCellValue("GYEE");               // 分公司简称
+            outputRow.createCell(7).setCellValue(name);                      // 测点描述
+
+            id++;
+        }
+
+        FileOutputStream fos = new FileOutputStream(outputPath);
+        outputWorkbook.write(fos);
+        fos.close();
+
+        inputWorkbook.close();
+        outputWorkbook.close();
+
+        System.out.println("处理完成,总共写入测点:" + (id - 1));
+    }
+}

+ 7 - 0
src/main/resources/application.yml

@@ -0,0 +1,7 @@
+server:
+  port: 8080  # 应用运行的端口
+  servlet:
+    context-path: /
+spring:
+  application:
+    name: demo  # 应用名称