活动介绍

public static String parseDocxToHtml(String filePath) { StringBuilder html = new StringBuilder(); try (OPCPackage opcPackage = OPCPackage.open(new File(filePath))) { XWPFDocument document = new XWPFDocument(opcPackage); // 处理段落 for (XWPFParagraph paragraph : document.getParagraphs()) { String paragraphContent = processRunsAndPictures(paragraph); if (paragraphContent.trim().isEmpty()) { continue; // 跳过空白段落 } String paragraphStyle = getParagraphStyle(paragraph); html.append("<p style=\"").append(paragraphStyle).append("\">").append(paragraphContent).append("</p>"); } // 处理表格(优化表格样式) for (XWPFTable table : document.getTables()) { html.append("<table style='border-collapse: collapse; width: 100%; border: 1px solid #000;'>"); for (XWPFTableRow row : table.getRows()) { html.append("<tr>"); for (XWPFTableCell cell : row.getTableCells()) { html.append("<td style='border: 1px solid #000; padding: 5px; text-align: left;'>"); for (XWPFParagraph para : cell.getParagraphs()) { String cellContent = processRunsAndPictures(para); html.append(cellContent.trim()); // 去除单元格内容前后空白 } html.append("</td>"); } html.append("</tr>"); } html.append("</table>"); } } catch (IOException | InvalidFormatException e) { System.err.println("解析 DOCX 文件时出现错误: " + e.getMessage()); } return html.toString(); } 这个是解析HTML的

时间: 2025-07-11 15:44:16 浏览: 27
<think>好的,我需要帮助用户了解如何使用Apache POI的XWPFDocument将DOCX文件转换为包含段落和表格的HTML。首先,我应该回顾一下Apache POI的相关知识,特别是处理DOCX文件的XWPF模块。用户提到需要转换段落和表格,所以我需要找出如何解析这些元素。 我记得Apache POI的XWPFDocument类可以读取DOCX文件,每个文档由多个段落(XWPFParagraph)和表格(XWPFTable)组成。接下来,我需要遍历这些元素,并将它们转换为对应的HTML标签,比如段落用<p>,表格用<table>、<tr>、<td>等。 然后,我需要考虑如何处理格式,比如文本样式(加粗、斜体)、超链接、列表等。可能要用到XWPFRun来获取文本样式,并生成相应的HTML标签,比如<strong>或<em>。表格可能需要递归处理行和单元格,特别是合并单元格的情况,但Apache POI的API可能不支持直接获取合并信息,这部分可能需要额外处理或者简化。 另外,用户可能希望生成的HTML结构良好,可能需要添加基本的HTML框架,如<html>和<body>标签。同时,要确保转换后的HTML保留原始文档的结构,比如段落之间的换行,表格的边框等。不过,复杂的样式(如颜色、字体大小)可能需要更复杂的处理,或者用户可能只需要基本的结构。 接下来,我需要编写示例代码,展示如何读取DOCX文件,遍历段落和表格,并构建HTML字符串。需要注意异常处理,比如文件不存在的情况,以及正确关闭资源。可能还需要处理图片,但用户没有提到,暂时可以忽略或简单注释说明。 最后,用户可能需要进一步的优化建议,比如使用第三方库(如documents4j)进行更高质量的转换,或者处理更复杂的样式。我应该提到这些可能性,并指出Apache POI的局限性,比如对高级格式支持有限,建议根据需求选择合适的工具。 现在,我需要检查代码是否正确使用XWPFDocument,是否正确处理段落和表格,HTML标签是否正确嵌套,以及是否有遗漏的元素(如列表、超链接)。可能还需要测试代码,确保示例能够运行,或者至少语法正确。同时,确保引用了相关的文档,比如Apache POI的官方资源,以增加可信度。</think>以下是使用Apache POI的`XWPFDocument`将DOCX转换为HTML的示例方法,包含段落和表格处理: ```java import org.apache.poi.xwpf.usermodel.*; import java.io.*; public class DocxToHtmlConverter { public static String convertDocxToHtml(File docxFile) throws IOException { StringBuilder html = new StringBuilder(); html.append("<html><body>"); try (XWPFDocument doc = new XWPFDocument(new FileInputStream(docxFile))) { // 处理段落 for (XWPFParagraph p : doc.getParagraphs()) { html.append("<p>"); for (XWPFRun run : p.getRuns()) { String text = run.getText(0); if (text != null) { // 处理粗体/斜体 if (run.isBold()) html.append("<strong>"); if (run.isItalic()) html.append("<em>"); html.append(text.replaceAll("\n", "<br/>")); if (run.isItalic()) html.append("</em>"); if (run.isBold()) html.append("</strong>"); } } html.append("</p>\n"); } // 处理表格 for (XWPFTable table : doc.getTables()) { html.append("<table border='1'>"); for (XWPFTableRow row : table.getRows()) { html.append("<tr>"); for (XWPFTableCell cell : row.getTableCells()) { html.append("<td>"); for (XWPFParagraph p : cell.getParagraphs()) { for (XWPFRun run : p.getRuns()) { html.append(run.getText(0)); } } html.append("</td>"); } html.append("</tr>"); } html.append("</table>\n"); } } html.append("</body></html>"); return html.toString(); } } ``` **改进建议**: 1. **样式增强**:添加CSS处理字体/颜色 ```java html.append("<style>body { font-family: Arial; }</style>"); ``` 2. **复杂表格**:处理合并单元格(需解析`CTTcPr`)[^1] 3. **图片处理**:提取嵌入图片并转为base64 ```java for (XWPFPictureData pic : doc.getAllPictures()) { String base64 = Base64.getEncoder().encodeToString(pic.getData()); html.append("<img src='data:image/png;base64," + base64 + "'>"); } ``` 4. **列表支持**:检测`numFmt`属性处理有序/无序列表[^1] **引用说明**: - 表格合并单元格解析需要访问`CTTcPr`的`gridSpan`属性 - 列表检测需检查段落`getNumFmt()`返回值[^1]
阅读全文

相关推荐

package com.towere.common.utils.poi; import com.towere.common.utils.StringUtils; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.xssf.eventusermodel.XSSFReader; import org.apache.poi.xssf.model.SharedStringsTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class DiskBasedExcelReader { private static final Logger log = LoggerFactory.getLogger(DiskBasedExcelReader.class); private OPCPackage pkg; private XSSFReader reader; private SharedStringsTable sst; private List<String> headers = new ArrayList<>(); // Initialize headers private int totalProcessedRows = 0; private final int chunkSize; public DiskBasedExcelReader(String filePath, int chunkSize) throws IOException, OpenXML4JException { if (filePath == null || filePath.isEmpty()) { throw new IllegalArgumentException("文件路径不能为空"); } if (chunkSize <= 0) { throw new IllegalArgumentException("分块大小必须大于0"); } this.chunkSize = chunkSize; this.pkg = OPCPackage.open(filePath, PackageAccess.READ); this.reader = new XSSFReader(pkg); this.sst = reader.getSharedStringsTable(); } public List<Map<String, String>> readNextChunk() throws IOException, SAXException, ParserConfigurationException { List<Map<String, String>> chunkData = new ArrayList<>(); SheetDataHandler sheetDataHandler = new SheetDataHandler(); try (InputStream sheetInputStream = getSheetInputStream()) { XMLReader parser = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); parser.setContentHandler(sheetDataHandler); InputSource sheetSource = new InputSource(sheetInputStream); parser.parse(sheetSource); } catch (Exception e) { log.error("解析Excel文件时出错", e); throw e; } while (chunkData.size() < chunkSize && sheetDataHandler.hasNext()) { RowData rowData = sheetDataHandler.next(); if (rowData != null) { Map<String, String> dataRow = parseRowData(rowData); if (!dataRow.isEmpty()) { chunkData.add(dataRow); } } } return chunkData; } private InputStream getSheetInputStream() throws IOException { PackagePart firstSheetPart = getFirstSheetPart(); return firstSheetPart.getInputStream(); } private PackagePart getFirstSheetPart() throws IOException { List relationships = pkg.getRelationshipsByType(XSSFReader.SHEET_RELATIONSHIP_TYPE); if (relationships == null || relationships.isEmpty()) { throw new IOException("Excel文件中没有工作表"); } PackageRelationship rel = relationships.get(0); String sheetPartName = rel.getTargetURI().toString(); return pkg.getPart(PackagePart.create(sheetPartName)); } private Map<String, String> parseRowData(RowData rowData) { Map<String, String> rowDataMap = new LinkedHashMap<>(); boolean hasRequiredData = false; for (int i = 0; i < headers.size(); i++) { String header = headers.get(i); if (header != null && !header.isEmpty()) { // Check if header is valid String cellValue = rowData.getCell(i); rowDataMap.put(header, cellValue); if (StringUtils.isNotBlank(cellValue)) { hasRequiredData = true; } } } return hasRequiredData ? rowDataMap : new LinkedHashMap<>(); } private class RowData { private List<String> cells; public RowData(List<String> cells) { this.cells = cells; } public String getCell(int index) { return index < cells.size() ? cells.get(index) : ""; } } private class SheetDataHandler extends DefaultHandler { private List<RowData> rows = new ArrayList<>(); private List<String> currentRow = new ArrayList<>(); private boolean isCell = false; private boolean isRow = false; private boolean isSharedString = false; private StringBuilder cellValue = new StringBuilder(); @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { if ("row".equals(qName)) { isRow = true; currentRow = new ArrayList<>(); } else if ("c".equals(qName)) { isCell = true; cellValue.setLength(0); } else if ("is".equals(qName)) { isSharedString = true; } } @Override public void endElement(String uri, String localName, String qName) { if ("row".equals(qName)) { isRow = false; rows.add(new RowData(currentRow)); } else if ("c".equals(qName)) { isCell = false; if (isSharedString) { try { int idx = Integer.parseInt(cellValue.toString()); String sharedString = String.valueOf(sst.getEntryAt(idx)); currentRow.add(sharedString); } catch (NumberFormatException e) { log.warn("无法解析共享字符串索引: {}", cellValue.toString()); currentRow.add(cellValue.toString()); } } else { currentRow.add(cellValue.toString()); } } else if ("is".equals(qName)) { isSharedString = false; } } @Override public void characters(char[] ch, int start, int length) { if (isCell) { cellValue.append(new String(ch, start, length).trim()); } } public boolean hasNext() { return !rows.isEmpty(); } public RowData next() { if (!hasNext()) { return null; } return rows.remove(0); } } public void close() { if (pkg != null) { try { pkg.close(); } catch (IOException e) { log.error("关闭OPCPackage时出错", e); } } } public static void main(String[] args) { try { DiskBasedExcelReader reader = new DiskBasedExcelReader("path/to/your/excel.xlsx", 100); List<Map<String, String>> chunkData; while ((chunkData = reader.readNextChunk()).size() > 0) { for (Map<String, String> row : chunkData) { System.out.println(row); } } reader.close(); } catch (Exception e) { e.printStackTrace(); } } } // 假设ExcelConstants类如下: class ExcelConstants { static final List<String> REQUIRED_HEADERS = List.of("Header1", "Header2", "Header3"); // 示例 } 修改直接再磁盘读取,零内存加载

using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Windows; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; [assembly: CommandClass(typeof(ArchitectureCADPlugin.Commands))] [assembly: CommandClass(typeof(ArchitectureCADPlugin.Loader))] namespace ArchitectureCADPlugin { public class Commands { // 存储识别的图层名称 private static string axisLayer = ""; private static string axisNumberLayer = ""; private static string dimensionLayer = ""; private static string beamLayer = ""; private static string columnLayer = ""; private static string wallLayer = ""; private static string cavityLayer = ""; // 存储识别的梁信息 private static Dictionary<string, BeamInfo> beamInfoDict = new Dictionary<string, BeamInfo>(); // AXISID -> AID [CommandMethod("AID", CommandFlags.Modal)] public void IdentifyAxis() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; // 点选识别轴网、轴号及标注尺寸图层 ed.WriteMessage("\n【轴网识别】请点选轴网图层中的对象: "); PromptEntityOptions peoAxis = new PromptEntityOptions("\n选择轴网对象: "); peoAxis.SetRejectMessage("\n请选择轴网对象!"); peoAxis.AddAllowedClass(typeof(Entity), true); PromptEntityResult perAxis = ed.GetEntity(peoAxis); if (perAxis.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity entAxis = tr.GetObject(perAxis.ObjectId, OpenMode.ForRead) as Entity; if (entAxis != null) { axisLayer = entAxis.Layer; ed.WriteMessage("\n已识别轴网图层: " + axisLayer); } ed.WriteMessage("\n【轴网识别】请点选轴号图层中的对象: "); PromptEntityOptions peoAxisNum = new PromptEntityOptions("\n选择轴号对象: "); peoAxisNum.SetRejectMessage("\n请选择轴号对象!"); peoAxisNum.AddAllowedClass(typeof(Entity), true); PromptEntityResult perAxisNum = ed.GetEntity(peoAxisNum); if (perAxisNum.Status == PromptStatus.OK) { Entity entAxisNum = tr.GetObject(perAxisNum.ObjectId, OpenMode.ForRead) as Entity; if (entAxisNum != null) { axisNumberLayer = entAxisNum.Layer; ed.WriteMessage("\n已识别轴号图层: " + axisNumberLayer); } } ed.WriteMessage("\n【轴网识别】请点选标注尺寸图层中的对象: "); PromptEntityOptions peoDim = new PromptEntityOptions("\n选择标注尺寸对象: "); peoDim.SetRejectMessage("\n请选择标注尺寸对象!"); peoDim.AddAllowedClass(typeof(Entity), true); PromptEntityResult perDim = ed.GetEntity(peoDim); if (perDim.Status == PromptStatus.OK) { Entity entDim = tr.GetObject(perDim.ObjectId, OpenMode.ForRead) as Entity; if (entDim != null) { dimensionLayer = entDim.Layer; ed.WriteMessage("\n已识别标注尺寸图层: " + dimensionLayer); } } ed.WriteMessage("\n【轴网识别】请框选所有图层: "); PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择对象: "; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status == PromptStatus.OK) { SelectionSet ss = psr.Value; foreach (ObjectId objId in ss.GetObjectIds()) { Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null) { if (ent.Layer == axisLayer) ed.WriteMessage("\n找到轴网对象: " + ent.GetType().Name); else if (ent.Layer == axisNumberLayer) ed.WriteMessage("\n找到轴号对象: " + ent.GetType().Name); else if (ent.Layer == dimensionLayer) ed.WriteMessage("\n找到标注尺寸对象: " + ent.GetType().Name); } } } tr.Commit(); } SaveLayerSettings(); } // BEAMSTAT -> BST [CommandMethod("BST", CommandFlags.Modal)] public void BeamStatistics() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; if (string.IsNullOrEmpty(beamLayer)) { ed.WriteMessage("\n【梁统计】请先使用 BID 命令识别梁线图层!"); return; } ed.WriteMessage("\n【梁统计】请框选所有图层: "); PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择对象: "; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status != PromptStatus.OK) return; Dictionary<string, int> beamCountDict = new Dictionary<string, int>(); Dictionary<string, int> sectionCountDict = new Dictionary<string, int>(); using (Transaction tr = db.TransactionManager.StartTransaction()) { SelectionSet ss = psr.Value; foreach (ObjectId objId in ss.GetObjectIds()) { Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null && ent.Layer == beamLayer) { string beamName = ExtractBeamName(ent); string sectionSize = ExtractSectionSize(ent); if (!string.IsNullOrEmpty(beamName)) { if (beamCountDict.ContainsKey(beamName)) beamCountDict[beamName]++; else beamCountDict.Add(beamName, 1); } else if (!string.IsNullOrEmpty(sectionSize)) { if (sectionCountDict.ContainsKey(sectionSize)) sectionCountDict[sectionSize]++; else sectionCountDict.Add(sectionSize, 1); } } } CreateBeamStatisticsTable(beamCountDict, sectionCountDict, tr); tr.Commit(); } } // BEAMID -> BID [CommandMethod("BID", CommandFlags.Modal)] public void IdentifyBeamLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; ed.WriteMessage("\n【梁识别】请点选梁线图层中的对象: "); PromptEntityOptions peo = new PromptEntityOptions("\n选择梁线对象: "); peo.SetRejectMessage("\n请选择梁线对象!"); peo.AddAllowedClass(typeof(Entity), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status == PromptStatus.OK) { using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { beamLayer = ent.Layer; ed.WriteMessage("\n已识别梁线图层: " + beamLayer); SaveLayerSettings(); } tr.Commit(); } } } // COLUMNID -> CID [CommandMethod("CID", CommandFlags.Modal)] public void IdentifyColumnLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; ed.WriteMessage("\n【柱识别】请点选柱图层中的对象: "); PromptEntityOptions peo = new PromptEntityOptions("\n选择柱对象: "); peo.SetRejectMessage("\n请选择柱对象!"); peo.AddAllowedClass(typeof(Entity), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status == PromptStatus.OK) { using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { columnLayer = ent.Layer; ed.WriteMessage("\n已识别柱图层: " + columnLayer); SaveLayerSettings(); } tr.Commit(); } } } // WALLID -> WID [CommandMethod("WID", CommandFlags.Modal)] public void IdentifyWallLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; ed.WriteMessage("\n【墙识别】请点选墙图层中的对象: "); PromptEntityOptions peo = new PromptEntityOptions("\n选择墙对象: "); peo.SetRejectMessage("\n请选择墙对象!"); peo.AddAllowedClass(typeof(Entity), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status == PromptStatus.OK) { using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { wallLayer = ent.Layer; ed.WriteMessage("\n已识别墙图层: " + wallLayer); SaveLayerSettings(); } tr.Commit(); } } } // EXPORTBEAM -> EB [CommandMethod("EB", CommandFlags.Modal)] public void ExportBeamToExcel() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n【导出梁表】请选择梁统计表格: "; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { SelectionSet ss = psr.Value; if (ss.Count == 1) { ObjectId tableId = ss.GetObjectIds()[0]; Table table = tr.GetObject(tableId, OpenMode.ForRead) as Table; if (table != null) { ExportTableToCSV(table); } } tr.Commit(); } } // LOADSETTINGS -> LS [CommandMethod("LS", CommandFlags.Modal)] public void LoadLayerSettings() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; axisLayer = Application.GetSystemVariable("AXIS_LAYER").ToString(); axisNumberLayer = Application.GetSystemVariable("AXIS_NUM_LAYER").ToString(); dimensionLayer = Application.GetSystemVariable("DIM_LAYER").ToString(); beamLayer = Application.GetSystemVariable("BEAM_LAYER").ToString(); columnLayer = Application.GetSystemVariable("COLUMN_LAYER").ToString(); wallLayer = Application.GetSystemVariable("WALL_LAYER").ToString(); cavityLayer = Application.GetSystemVariable("CAVITY_LAYER").ToString(); ed.WriteMessage("\n已加载图层设置:"); ed.WriteMessage("\n轴网图层: " + axisLayer); ed.WriteMessage("\n轴号图层: " + axisNumberLayer); ed.WriteMessage("\n标注尺寸图层: " + dimensionLayer); ed.WriteMessage("\n梁线图层: " + beamLayer); ed.WriteMessage("\n柱图层: " + columnLayer); ed.WriteMessage("\n墙图层: " + wallLayer); } // SHOWSETTINGS -> SS [CommandMethod("SS", CommandFlags.Modal)] public void ShowLayerSettings() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; ed.WriteMessage("\n当前图层设置:"); ed.WriteMessage("\n轴网图层: " + axisLayer); ed.WriteMessage("\n轴号图层: " + axisNumberLayer); ed.WriteMessage("\n标注尺寸图层: " + dimensionLayer); ed.WriteMessage("\n梁线图层: " + beamLayer); ed.WriteMessage("\n柱图层: " + columnLayer); ed.WriteMessage("\n墙图层: " + wallLayer); ed.WriteMessage("\n空洞图层: " + cavityLayer); } private void SaveLayerSettings() { Application.SetSystemVariable("AXIS_LAYER", axisLayer); Application.SetSystemVariable("AXIS_NUM_LAYER", axisNumberLayer); Application.SetSystemVariable("DIM_LAYER", dimensionLayer); Application.SetSystemVariable("BEAM_LAYER", beamLayer); Application.SetSystemVariable("COLUMN_LAYER", columnLayer); Application.SetSystemVariable("WALL_LAYER", wallLayer); Application.SetSystemVariable("CAVITY_LAYER", cavityLayer); } private string ExtractBeamName(Entity ent) { // 示例实现 - 实际应根据项目需求完善 if (ent is DBText text) return text.TextString; return string.Empty; } private string ExtractSectionSize(Entity ent) { // 示例实现 - 实际应根据项目需求完善 if (ent is MText mtext) return mtext.Text; if (ent is DBText text) return text.TextString; return string.Empty; } private void CreateBeamStatisticsTable(Dictionary<string, int> beamCountDict, Dictionary<string, int> sectionCountDict, Transaction tr) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptPointOptions ppo = new PromptPointOptions("\n【梁统计】请指定表格插入点: "); PromptPointResult ppr = ed.GetPoint(ppo); if (ppr.Status != PromptStatus.OK) return; Point3d insertPoint = ppr.Value; List<BeamStatItem> statItems = new List<BeamStatItem>(); foreach (var pair in beamCountDict) { BeamInfo beamInfo = null; if (beamInfoDict.TryGetValue(pair.Key, out beamInfo)) { statItems.Add(new BeamStatItem { Name = pair.Key, SectionSize = beamInfo.SectionSize, Count = pair.Value }); } else { // 如果梁信息字典中没有对应的梁信息,添加一个默认项 statItems.Add(new BeamStatItem { Name = pair.Key, SectionSize = "未知尺寸", Count = pair.Value }); } } foreach (var pair in sectionCountDict) { statItems.Add(new BeamStatItem { Name = "", SectionSize = pair.Key, Count = pair.Value }); } foreach (var item in statItems) { if (item.SectionSize != "未知尺寸") { string sizeText = item.SectionSize.Replace("x", "*"); string[] parts = sizeText.Split('*'); if (parts.Length == 2 && double.TryParse(parts[0], out double width) && double.TryParse(parts[1], out double height)) { item.Area = width * height / 1000000; item.Load = item.Area * 25; } } } statItems = statItems.OrderByDescending(i => i.Load).ToList(); Table table = new Table(); table.SetDatabaseDefaults(); table.TableStyle = db.Tablestyle; table.Position = insertPoint; // 设置行数和列数 int rowCount = 2 + statItems.Count; int colCount = 6; table.SetSize(rowCount, colCount); // 设置列宽 for (int i = 0; i < colCount; i++) { switch (i) { case 0: table.Columns[i].Width = 100; break; case 1: table.Columns[i].Width = 200; break; case 2: table.Columns[i].Width = 150; break; case 3: table.Columns[i].Width = 100; break; case 4: table.Columns[i].Width = 150; break; case 5: table.Columns[i].Width = 150; break; } } // 设置标题行 table.Cells[0, 0].Value = "梁截面尺寸汇总表"; table.Cells[0, 0].Alignment = CellAlignment.MiddleCenter; table.Cells[0, 0].TextHeight = 50; table.MergeCells(CellRange.Create(table, 0, 0, 0, colCount - 1)); // 设置表头 string[] headers = { "序号", "梁名称", "梁截面尺寸mm", "数量", "截面面积㎡", "集中线荷载(KN/m)" }; for (int i = 0; i < headers.Length; i++) { table.Cells[1, i].Value = headers[i]; table.Cells[1, i].Alignment = CellAlignment.MiddleCenter; table.Cells[1, i].TextHeight = 35; } // 添加数据行 for (int i = 0; i < statItems.Count; i++) { var item = statItems[i]; table.Cells[2 + i, 0].Value = (i + 1).ToString(); table.Cells[2 + i, 1].Value = item.Name; table.Cells[2 + i, 2].Value = item.SectionSize; table.Cells[2 + i, 3].Value = item.Count.ToString(); table.Cells[2 + i, 4].Value = item.Area.ToString("F6"); table.Cells[2 + i, 5].Value = item.Load.ToString("F2"); for (int j = 0; j < headers.Length; j++) { table.Cells[2 + i, j].Alignment = CellAlignment.MiddleCenter; table.Cells[2 + i, j].TextHeight = 30; } } BlockTableRecord btr = (BlockTableRecord)tr.GetObject( doc.Database.CurrentSpaceId, OpenMode.ForWrite); btr.AppendEntity(table); tr.AddNewlyCreatedDBObject(table, true); ed.WriteMessage("\n【梁统计】已生成梁统计表格"); } private void ExportTableToCSV(Table table) { try { // 使用AutoCAD内置的FileDialog string filePath = FileDialog.GetSaveFileName( "【梁统计】保存梁统计表格", // 对话框标题 "梁截面尺寸汇总表.csv", // 默认文件名 "csv", // 默认扩展名 "CSV文件|*.csv", // 文件过滤器 FileDialog.GetSaveFileNameFlags.None ); if (string.IsNullOrEmpty(filePath)) return; // 确保文件扩展名正确 if (!filePath.EndsWith(".csv", StringComparison.OrdinalIgnoreCase)) { filePath += ".csv"; } // 创建CSV内容 StringBuilder csvContent = new StringBuilder(); // 添加标题行 csvContent.AppendLine("序号,梁名称,梁截面尺寸mm,数量,截面面积㎡,集中线荷载(KN/m)"); // 添加数据行(跳过标题行) for (int row = 2; row < table.Rows.Count; row++) { List<string> rowData = new List<string>(); for (int col = 0; col < table.Columns.Count; col++) { if (table.Cells[row, col] != null) { string value = table.Cells[row, col].Value?.ToString() ?? ""; // 处理可能包含逗号的内容 if (value.Contains(",")) value = "\"" + value + "\""; rowData.Add(value); } } csvContent.AppendLine(string.Join(",", rowData)); } // 写入文件 File.WriteAllText(filePath, csvContent.ToString(), Encoding.UTF8); // 显示成功消息 Application.ShowAlertDialog("表格已成功导出到:\n" + filePath); } catch (System.Exception ex) { Application.ShowAlertDialog("导出CSV时出错:\n" + ex.Message); } } } public class BeamInfo { public string Name { get; set; } public string SectionSize { get; set; } public string Elevation { get; set; } } public class BeamStatItem { public string Name { get; set; } public string SectionSize { get; set; } public int Count { get; set; } public double Area { get; set; } public double Load { get; set; } } public class Loader { [CommandMethod("LOADARCHPLUGIN", CommandFlags.Modal)] public void LoadPlugin() { Application.ShowAlertDialog("建筑CAD识别与标注插件已加载!"); } } } 存在以下问题: CS0103当前上下文中不存在名称“FileDialog” CS0103当前上下文中不存在名称FileDialog”using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Windows; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; [assembly: CommandClass(typeof(ArchitectureCADPlugin.Commands))] [assembly: CommandClass(typeof(ArchitectureCADPlugin.Loader))] namespace ArchitectureCADPlugin { public class Commands { // 存储识别的图层名称 private static string axisLayer = ""; private static string axisNumberLayer = ""; private static string dimensionLayer = ""; private static string beamLayer = ""; private static string columnLayer = ""; private static string wallLayer = ""; private static string cavityLayer = ""; // 存储识别的梁信息 private static Dictionary<string, BeamInfo> beamInfoDict = new Dictionary<string, BeamInfo>(); // AXISID -> AID [CommandMethod("AID", CommandFlags.Modal)] public void IdentifyAxis() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; // 点选识别轴网、轴号及标注尺寸图层 ed.WriteMessage("\n【轴网识别】请点选轴网图层中的对象: "); PromptEntityOptions peoAxis = new PromptEntityOptions("\n选择轴网对象: "); peoAxis.SetRejectMessage("\n请选择轴网对象!"); peoAxis.AddAllowedClass(typeof(Entity), true); PromptEntityResult perAxis = ed.GetEntity(peoAxis); if (perAxis.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity entAxis = tr.GetObject(perAxis.ObjectId, OpenMode.ForRead) as Entity; if (entAxis != null) { axisLayer = entAxis.Layer; ed.WriteMessage("\n已识别轴网图层: " + axisLayer); } ed.WriteMessage("\n【轴网识别】请点选轴号图层中的对象: "); PromptEntityOptions peoAxisNum = new PromptEntityOptions("\n选择轴号对象: "); peoAxisNum.SetRejectMessage("\n请选择轴号对象!"); peoAxisNum.AddAllowedClass(typeof(Entity), true); PromptEntityResult perAxisNum = ed.GetEntity(peoAxisNum); if (perAxisNum.Status == PromptStatus.OK) { Entity entAxisNum = tr.GetObject(perAxisNum.ObjectId, OpenMode.ForRead) as Entity; if (entAxisNum != null) { axisNumberLayer = entAxisNum.Layer; ed.WriteMessage("\n已识别轴号图层: " + axisNumberLayer); } } ed.WriteMessage("\n【轴网识别】请点选标注尺寸图层中的对象: "); PromptEntityOptions peoDim = new PromptEntityOptions("\n选择标注尺寸对象: "); peoDim.SetRejectMessage("\n请选择标注尺寸对象!"); peoDim.AddAllowedClass(typeof(Entity), true); PromptEntityResult perDim = ed.GetEntity(peoDim); if (perDim.Status == PromptStatus.OK) { Entity entDim = tr.GetObject(perDim.ObjectId, OpenMode.ForRead) as Entity; if (entDim != null) { dimensionLayer = entDim.Layer; ed.WriteMessage("\n已识别标注尺寸图层: " + dimensionLayer); } } ed.WriteMessage("\n【轴网识别】请框选所有图层: "); PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择对象: "; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status == PromptStatus.OK) { SelectionSet ss = psr.Value; foreach (ObjectId objId in ss.GetObjectIds()) { Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null) { if (ent.Layer == axisLayer) ed.WriteMessage("\n找到轴网对象: " + ent.GetType().Name); else if (ent.Layer == axisNumberLayer) ed.WriteMessage("\n找到轴号对象: " + ent.GetType().Name); else if (ent.Layer == dimensionLayer) ed.WriteMessage("\n找到标注尺寸对象: " + ent.GetType().Name); } } } tr.Commit(); } SaveLayerSettings(); } // BEAMSTAT -> BST [CommandMethod("BST", CommandFlags.Modal)] public void BeamStatistics() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; if (string.IsNullOrEmpty(beamLayer)) { ed.WriteMessage("\n【梁统计】请先使用 BID 命令识别梁线图层!"); return; } ed.WriteMessage("\n【梁统计】请框选所有图层: "); PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择对象: "; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status != PromptStatus.OK) return; Dictionary<string, int> beamCountDict = new Dictionary<string, int>(); Dictionary<string, int> sectionCountDict = new Dictionary<string, int>(); using (Transaction tr = db.TransactionManager.StartTransaction()) { SelectionSet ss = psr.Value; foreach (ObjectId objId in ss.GetObjectIds()) { Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null && ent.Layer == beamLayer) { string beamName = ExtractBeamName(ent); string sectionSize = ExtractSectionSize(ent); if (!string.IsNullOrEmpty(beamName)) { if (beamCountDict.ContainsKey(beamName)) beamCountDict[beamName]++; else beamCountDict.Add(beamName, 1); } else if (!string.IsNullOrEmpty(sectionSize)) { if (sectionCountDict.ContainsKey(sectionSize)) sectionCountDict[sectionSize]++; else sectionCountDict.Add(sectionSize, 1); } } } CreateBeamStatisticsTable(beamCountDict, sectionCountDict, tr); tr.Commit(); } } // BEAMID -> BID [CommandMethod("BID", CommandFlags.Modal)] public void IdentifyBeamLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; ed.WriteMessage("\n【梁识别】请点选梁线图层中的对象: "); PromptEntityOptions peo = new PromptEntityOptions("\n选择梁线对象: "); peo.SetRejectMessage("\n请选择梁线对象!"); peo.AddAllowedClass(typeof(Entity), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status == PromptStatus.OK) { using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { beamLayer = ent.Layer; ed.WriteMessage("\n已识别梁线图层: " + beamLayer); SaveLayerSettings(); } tr.Commit(); } } } // COLUMNID -> CID [CommandMethod("CID", CommandFlags.Modal)] public void IdentifyColumnLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; ed.WriteMessage("\n【柱识别】请点选柱图层中的对象: "); PromptEntityOptions peo = new PromptEntityOptions("\n选择柱对象: "); peo.SetRejectMessage("\n请选择柱对象!"); peo.AddAllowedClass(typeof(Entity), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status == PromptStatus.OK) { using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { columnLayer = ent.Layer; ed.WriteMessage("\n已识别柱图层: " + columnLayer); SaveLayerSettings(); } tr.Commit(); } } } // WALLID -> WID [CommandMethod("WID", CommandFlags.Modal)] public void IdentifyWallLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; ed.WriteMessage("\n【墙识别】请点选墙图层中的对象: "); PromptEntityOptions peo = new PromptEntityOptions("\n选择墙对象: "); peo.SetRejectMessage("\n请选择墙对象!"); peo.AddAllowedClass(typeof(Entity), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status == PromptStatus.OK) { using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { wallLayer = ent.Layer; ed.WriteMessage("\n已识别墙图层: " + wallLayer); SaveLayerSettings(); } tr.Commit(); } } } // EXPORTBEAM -> EB [CommandMethod("EB", CommandFlags.Modal)] public void ExportBeamToExcel() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n【导出梁表】请选择梁统计表格: "; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { SelectionSet ss = psr.Value; if (ss.Count == 1) { ObjectId tableId = ss.GetObjectIds()[0]; Table table = tr.GetObject(tableId, OpenMode.ForRead) as Table; if (table != null) { ExportTableToCSV(table); } } tr.Commit(); } } // LOADSETTINGS -> LS [CommandMethod("LS", CommandFlags.Modal)] public void LoadLayerSettings() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; axisLayer = Application.GetSystemVariable("AXIS_LAYER").ToString(); axisNumberLayer = Application.GetSystemVariable("AXIS_NUM_LAYER").ToString(); dimensionLayer = Application.GetSystemVariable("DIM_LAYER").ToString(); beamLayer = Application.GetSystemVariable("BEAM_LAYER").ToString(); columnLayer = Application.GetSystemVariable("COLUMN_LAYER").ToString(); wallLayer = Application.GetSystemVariable("WALL_LAYER").ToString(); cavityLayer = Application.GetSystemVariable("CAVITY_LAYER").ToString(); ed.WriteMessage("\n已加载图层设置:"); ed.WriteMessage("\n轴网图层: " + axisLayer); ed.WriteMessage("\n轴号图层: " + axisNumberLayer); ed.WriteMessage("\n标注尺寸图层: " + dimensionLayer); ed.WriteMessage("\n梁线图层: " + beamLayer); ed.WriteMessage("\n柱图层: " + columnLayer); ed.WriteMessage("\n墙图层: " + wallLayer); } // SHOWSETTINGS -> SS [CommandMethod("SS", CommandFlags.Modal)] public void ShowLayerSettings() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; ed.WriteMessage("\n当前图层设置:"); ed.WriteMessage("\n轴网图层: " + axisLayer); ed.WriteMessage("\n轴号图层: " + axisNumberLayer); ed.WriteMessage("\n标注尺寸图层: " + dimensionLayer); ed.WriteMessage("\n梁线图层: " + beamLayer); ed.WriteMessage("\n柱图层: " + columnLayer); ed.WriteMessage("\n墙图层: " + wallLayer); ed.WriteMessage("\n空洞图层: " + cavityLayer); } private void SaveLayerSettings() { Application.SetSystemVariable("AXIS_LAYER", axisLayer); Application.SetSystemVariable("AXIS_NUM_LAYER", axisNumberLayer); Application.SetSystemVariable("DIM_LAYER", dimensionLayer); Application.SetSystemVariable("BEAM_LAYER", beamLayer); Application.SetSystemVariable("COLUMN_LAYER", columnLayer); Application.SetSystemVariable("WALL_LAYER", wallLayer); Application.SetSystemVariable("CAVITY_LAYER", cavityLayer); } private string ExtractBeamName(Entity ent) { // 示例实现 - 实际应根据项目需求完善 if (ent is DBText text) return text.TextString; return string.Empty; } private string ExtractSectionSize(Entity ent) { // 示例实现 - 实际应根据项目需求完善 if (ent is MText mtext) return mtext.Text; if (ent is DBText text) return text.TextString; return string.Empty; } private void CreateBeamStatisticsTable(Dictionary<string, int> beamCountDict, Dictionary<string, int> sectionCountDict, Transaction tr) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptPointOptions ppo = new PromptPointOptions("\n【梁统计】请指定表格插入点: "); PromptPointResult ppr = ed.GetPoint(ppo); if (ppr.Status != PromptStatus.OK) return; Point3d insertPoint = ppr.Value; List<BeamStatItem> statItems = new List<BeamStatItem>(); foreach (var pair in beamCountDict) { BeamInfo beamInfo = null; if (beamInfoDict.TryGetValue(pair.Key, out beamInfo)) { statItems.Add(new BeamStatItem { Name = pair.Key, SectionSize = beamInfo.SectionSize, Count = pair.Value }); } else { // 如果梁信息字典中没有对应的梁信息,添加一个默认项 statItems.Add(new BeamStatItem { Name = pair.Key, SectionSize = "未知尺寸", Count = pair.Value }); } } foreach (var pair in sectionCountDict) { statItems.Add(new BeamStatItem { Name = "", SectionSize = pair.Key, Count = pair.Value }); } foreach (var item in statItems) { if (item.SectionSize != "未知尺寸") { string sizeText = item.SectionSize.Replace("x", "*"); string[] parts = sizeText.Split('*'); if (parts.Length == 2 && double.TryParse(parts[0], out double width) && double.TryParse(parts[1], out double height)) { item.Area = width * height / 1000000; item.Load = item.Area * 25; } } } statItems = statItems.OrderByDescending(i => i.Load).ToList(); Table table = new Table(); table.SetDatabaseDefaults(); table.TableStyle = db.Tablestyle; table.Position = insertPoint; // 设置行数和列数 int rowCount = 2 + statItems.Count; int colCount = 6; table.SetSize(rowCount, colCount); // 设置列宽 for (int i = 0; i < colCount; i++) { switch (i) { case 0: table.Columns[i].Width = 100; break; case 1: table.Columns[i].Width = 200; break; case 2: table.Columns[i].Width = 150; break; case 3: table.Columns[i].Width = 100; break; case 4: table.Columns[i].Width = 150; break; case 5: table.Columns[i].Width = 150; break; } } // 设置标题行 table.Cells[0, 0].Value = "梁截面尺寸汇总表"; table.Cells[0, 0].Alignment = CellAlignment.MiddleCenter; table.Cells[0, 0].TextHeight = 50; table.MergeCells(CellRange.Create(table, 0, 0, 0, colCount - 1)); // 设置表头 string[] headers = { "序号", "梁名称", "梁截面尺寸mm", "数量", "截面面积㎡", "集中线荷载(KN/m)" }; for (int i = 0; i < headers.Length; i++) { table.Cells[1, i].Value = headers[i]; table.Cells[1, i].Alignment = CellAlignment.MiddleCenter; table.Cells[1, i].TextHeight = 35; } // 添加数据行 for (int i = 0; i < statItems.Count; i++) { var item = statItems[i]; table.Cells[2 + i, 0].Value = (i + 1).ToString(); table.Cells[2 + i, 1].Value = item.Name; table.Cells[2 + i, 2].Value = item.SectionSize; table.Cells[2 + i, 3].Value = item.Count.ToString(); table.Cells[2 + i, 4].Value = item.Area.ToString("F6"); table.Cells[2 + i, 5].Value = item.Load.ToString("F2"); for (int j = 0; j < headers.Length; j++) { table.Cells[2 + i, j].Alignment = CellAlignment.MiddleCenter; table.Cells[2 + i, j].TextHeight = 30; } } BlockTableRecord btr = (BlockTableRecord)tr.GetObject( doc.Database.CurrentSpaceId, OpenMode.ForWrite); btr.AppendEntity(table); tr.AddNewlyCreatedDBObject(table, true); ed.WriteMessage("\n【梁统计】已生成梁统计表格"); } private void ExportTableToCSV(Table table) { try { // 使用AutoCAD内置的FileDialog string filePath = FileDialog.GetSaveFileName( "【梁统计】保存梁统计表格", // 对话框标题 "梁截面尺寸汇总表.csv", // 默认文件名 "csv", // 默认扩展名 "CSV文件|*.csv", // 文件过滤器 FileDialog.GetSaveFileNameFlags.None ); if (string.IsNullOrEmpty(filePath)) return; // 确保文件扩展名正确 if (!filePath.EndsWith(".csv", StringComparison.OrdinalIgnoreCase)) { filePath += ".csv"; } // 创建CSV内容 StringBuilder csvContent = new StringBuilder(); // 添加标题行 csvContent.AppendLine("序号,梁名称,梁截面尺寸mm,数量,截面面积㎡,集中线荷载(KN/m)"); // 添加数据行(跳过标题行) for (int row = 2; row < table.Rows.Count; row++) { List<string> rowData = new List<string>(); for (int col = 0; col < table.Columns.Count; col++) { if (table.Cells[row, col] != null) { string value = table.Cells[row, col].Value?.ToString() ?? ""; // 处理可能包含逗号的内容 if (value.Contains(",")) value = "\"" + value + "\""; rowData.Add(value); } } csvContent.AppendLine(string.Join(",", rowData)); } // 写入文件 File.WriteAllText(filePath, csvContent.ToString(), Encoding.UTF8); // 显示成功消息 Application.ShowAlertDialog("表格已成功导出到:\n" + filePath); } catch (System.Exception ex) { Application.ShowAlertDialog("导出CSV时出错:\n" + ex.Message); } } } public class BeamInfo { public string Name { get; set; } public string SectionSize { get; set; } public string Elevation { get; set; } } public class BeamStatItem { public string Name { get; set; } public string SectionSize { get; set; } public int Count { get; set; } public double Area { get; set; } public double Load { get; set; } } public class Loader { [CommandMethod("LOADARCHPLUGIN", CommandFlags.Modal)] public void LoadPlugin() { Application.ShowAlertDialog("建筑CAD识别与标注插件已加载!"); } } } 存在以下问题: CS0103当前上下文中不存在名称“FileDialog” CS0103当前上下文中不存在名称FileDialog” 请根据以上问题将原代码修改一套完整代码

package com.isa.navi.library.map; import android.inputmethodservice.Keyboard; import android.os.Environment; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import androidx.annotation.NonNull; import com.isa.navi.library.constant.Const; import com.isa.navi.library.manager.BaseProxy; import com.isa.navi.library.map.DataCheckInfo; import com.isa.navi.library.map.UpdateEnvironment; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.CopyOnWriteArrayList; /** * @author haoj * @description description * @date 2023-06-20 */ public class MapProxy extends BaseProxy<IMapProxyAIDL> implements IMapProxy { private static final String TAG = Const.ISA_NAVI + "MapProxy"; private List<IMapListener.IMapChangeListener> mIUpdateCallbackListeners = new CopyOnWriteArrayList<>(); private IMapDownloadCallbackAIDL mIMapDownloadCallBackAIDL; private volatile static MapProxy mInstance; public static MapProxy getInstance() { if (mInstance == null) { synchronized (MapProxy.class) { if (mInstance == null) { mInstance = new MapProxy(); } } } return mInstance; } @Override protected String getProxyName() { return Const.SVR_MAP_REPOSITORY; } @Override protected IMapProxyAIDL getProxyService(IBinder iBinder) { return IMapProxyAIDL.Stub.asInterface(iBinder); } @Override public void updateMap() { try { if (isAvailable()) { mService.updateMap(); } } catch (RemoteException e) { e.printStackTrace(); } } @Override public void suspendUpdate(boolean suspend) { try { Log.d(TAG, "suspendUpdateMap suspend : " + suspend + ", isAvailable : " + isAvailable()); if (isAvailable()) { mService.suspendUpdate(suspend); } } catch (RemoteException e) { e.printStackTrace(); } } @Override public void cancelUpdateMap() { try { Log.d(TAG, "cancelUpdateMap : " + ", isAvailable : " + isAvailable()); if (isAvailable()) { mService.cancelUpdate(); } } catch (RemoteException e) { e.printStackTrace(); } } @Override public void addMapChangeListener(IMapListener.IMapChangeListener listener) { Log.d(TAG, "addDataChangeListener callback:" + listener + ", isAvailable : " + isAvailable()); try { if (isAvailable()) { if ((listener != null) && !mIUpdateCallbackListeners.contains(listener)) { mIUpdateCallbackListeners.add(listener); } if (mIUpdateCallbackListeners.size() == 1) { mIMapDownloadCallBackAIDL = new IMapDownloadCallbackAIDL.Stub() { @Override public void onMapDownloadStatusChange(List<UpdateInfoBean> bean) throws RemoteException { Log.d(TAG, "onMapDownloadStatusChange:" + bean + " ,size:" + mIUpdateCallbackListeners.size()); try { Iterator<IMapListener.IMapChangeListener> iterator = mIUpdateCallbackListeners.iterator(); while (iterator.hasNext()) { IMapListener.IMapChangeListener l = iterator.next(); l.onMapChange(bean); } } catch (Exception e) { e.printStackTrace(); } } }; mService.registerMapDownloadListener(mIMapDownloadCallBackAIDL); } } } catch (RemoteException e) { e.printStackTrace(); } } @Override public void removeMapChangeListener(IMapListener.IMapChangeListener listener) { Log.d(TAG, "removeDataChangeListener callback:" + listener + ", isAvailable : " + isAvailable()); try { if (isAvailable()) { if ((listener != null) && mIUpdateCallbackListeners.contains(listener)) { mIUpdateCallbackListeners.remove(listener); } if (mIUpdateCallbackListeners.size() == 0 && mIMapDownloadCallBackAIDL != null) { mService.unregisterMapDownloadListener(mIMapDownloadCallBackAIDL); } mIMapDownloadCallBackAIDL = null; } } catch (RemoteException e) { e.printStackTrace(); } } private static String calculateMD5(String filePath) { try { MessageDigest digest = MessageDigest.getInstance("MD5"); FileInputStream fis = new FileInputStream(filePath); byte[] buffer = new byte[8192]; int read = 0; while ((read = fis.read(buffer)) > 0) { digest.update(buffer, 0, read); } byte[] md5sum = digest.digest(); StringBuffer hexString = new StringBuffer(); for (int i = 0; i < md5sum.length; i++) { String hex = Integer.toHexString(0xff & md5sum[i]); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString(); } catch (Exception e) { e.printStackTrace(); return ""; } } private Map<String, String> getDetectionInfo(String md5_file_path) throws JSONException { Map<String, String> dataMap = new HashMap<>(); boolean isUsbReady = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); if(!isUsbReady) { return dataMap; } JSONObject jsonObject = getJsonObject(md5_file_path); JSONArray jsonArray = jsonObject.getJSONArray("ISAData"); for(int i = 0; i< jsonArray.length(); i++) { JSONObject jsonObject1 = jsonArray.getJSONObject(i); String dataName = jsonObject1.getString("data_name"); String md5 = jsonObject1.getString("md5"); dataMap.put(dataName, md5); } return dataMap; } @NonNull private static JSONObject getJsonObject(String md5_file_path) throws JSONException { File file = new File(md5_file_path); StringBuilder content = new StringBuilder(); try{ BufferedReader reader = new BufferedReader(new FileReader(file)); String line; while ((line = reader.readLine()) != null) { content.append(line).append("\n"); } reader.close(); } catch (IOException e) { throw new RuntimeException(e); } JSONObject jsonObject = new JSONObject(content.toString()); return jsonObject; } public DataCheckInfo checkISAData(String md5_file_path) { DataCheckInfo info = new DataCheckInfo(); md5_file_path += "/ISADataCheckInfo.txt"; Log.d(TAG, "checkISAData md5_file_path = " + md5_file_path); //获取文件信息,用于校验数据 Map<String, String> md5_file_map = null; try { md5_file_map = getDetectionInfo(md5_file_path); } catch (JSONException e) { e.printStackTrace(); } //如果文件中的信息不足32个则返回报错信息 if(md5_file_map.isEmpty() || md5_file_map.size() != 32) { info.setIs_result(false); info.setFailure(2); info.setReasom_chinese("ISADataCheckInfo.txt文件信息缺失"); info.setReasom_engine("Insufficient information in ISADataCheckInfo.txt"); Log.d(TAG, "checkISAData md5_file_map 信息不足"); return info; } // public String get_Global_m_data_address() { // return mHmiProxyJNI.get_Global_m_data_address(); // } //在数据分区下,检索数据 String data_path = "/map/"; File directory = new File(data_path); Map<String, String> data_MD5_map = new HashMap<>(); if(directory.exists() && directory.isDirectory()) { File[] files = directory.listFiles(); if (files != null) { for(File file :files) { if(file.isFile()) { String file_name = file.getName(); if(file_name.indexOf("CarDBBIN") != -1 || file_name.indexOf("Country_CarDB") != -1) { String MD5 = ""; MD5 = calculateMD5(data_path+file_name); if(MD5 == "") { info.setIs_result(false); info.setFailure(4); info.setReasom_chinese("无法计算分区内数据MD5值"); info.setReasom_engine("Unable to calculate MD5 of data within the partition"); return info; } Log.d(TAG, "checkISAData file_name:" + file_name); Log.d(TAG, "checkISAData MD5:" + MD5); data_MD5_map.put(file_name, MD5); } } } } else { info.setIs_result(false); info.setFailure(3); info.setReasom_chinese("无法访问数据分区"); info.setReasom_engine("Unable to read data partition"); Log.d(TAG, "checkISAData 无法读取数据分区目录"); return info; } } else { info.setIs_result(false); info.setFailure(8); info.setReasom_chinese("数据分区不存在"); info.setReasom_engine("The data partition does not exist"); Log.d(TAG, "checkISAData 数据分区目录不存在"); return info; } Log.d(TAG, "data_MD5_map 组织完毕!"); //如果数据不足32个,则返回报错 if(data_MD5_map.size() != 32) { info.setIs_result(false); info.setFailure(5); info.setReasom_chinese("数据分区目录下数据缺失"); info.setReasom_engine("Data is missing in the data partition directory"); Log.d(TAG, "checkISAData 数据分区目录目录下数据不全"); return info; } //遍历data_MD5_map集合,跟校验信息进行判断 for(Map.Entry<String, String> entry: data_MD5_map.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); String md5_file_map_value = md5_file_map.get(key); if(md5_file_map_value != null) { Log.d(TAG, "value:" + value); Log.d(TAG, "md5_file_map_value:" + md5_file_map_value); if(!value.equals(md5_file_map_value)) { Log.d(TAG, "value size:" + value.length()); Log.d(TAG, "md5_file_map_value size:" + md5_file_map_value.length()); info.setIs_result(false); info.setFailure(6); info.setReasom_chinese(key + " 该国家数据校验不通过"); info.setReasom_engine(key + " verification failed"); Log.d(TAG, "checkISAData " + key + "该国家数据校验不通过"); } } else { info.setIs_result(false); info.setFailure(7); info.setReasom_chinese(key + " 无法获取分区内数据MD5值"); info.setReasom_engine(key + " MD5 value calculation failed"); Log.d(TAG, "checkISAData MD5值计算失败"); return info; } } info.setIs_result(true); return info; } public String getInfoAfterUpdates() { String result = ""; // try { // if (isAvailable()) { // result = mService.getInfoAfterUpdates(); // } // } catch (RemoteException e) { // e.printStackTrace(); // } return result; } public void startUSBDetection() { try { Log.d(TAG, "getVersion : " + ", isAvailable : " + isAvailable()); if (isAvailable()) { mService.startUSBDetection(); } } catch (RemoteException e) { e.printStackTrace(); } } @Override public String getMapInfo() { String result = ""; try { if (isAvailable()) { result = mService.getMapInfo(); } } catch (RemoteException e) { e.printStackTrace(); } return result; } @Override public String getUpdateVersion() { String result = ""; try { if (isAvailable()) { result = mService.getUpdateVersion(); } } catch (RemoteException e) { e.printStackTrace(); } return result; } @Override public UpdateEnvironment checkUpdateEnvironment() { UpdateEnvironment result = null; try { if (isAvailable()) { result = mService.checkUpdateEnvironment(); Log.i(TAG, "result.getResult()" + result.getResult()); Log.i(TAG, "result.getReason()" + result.getReason()); } } catch (RemoteException e) { e.printStackTrace(); } return result; } @Override public String getUpdatePurpose() { String result = ""; try { if (isAvailable()) { result = mService.getUpdatePurpose(); } } catch (RemoteException e) { e.printStackTrace(); } return result; } @Override public String getUpdateContent() { String result = ""; try { if (isAvailable()) { result = mService.getUpdateContent(); } } catch (RemoteException e) { e.printStackTrace(); } return result; } @Override public String getUserManual() { String result = ""; try { if (isAvailable()) { result = mService.getUserManual(); } } catch (RemoteException e) { e.printStackTrace(); } return result; } @Override public String getUpdatedContentDescription() { String result = ""; try { if (isAvailable()) { result = mService.getUpdatedContentDescription(); } } catch (RemoteException e) { e.printStackTrace(); } return result; } @Override public int getEstimatedTime() { int result = 0; try { if (isAvailable()) { result = mService.getEstimatedTime(); } } catch (RemoteException e) { e.printStackTrace(); } return result; } @Override public boolean validatePassword(String inputPassword) { try { if (isAvailable()) { return mService.validatePassword(inputPassword); } } catch (Exception e) { e.printStackTrace(); } return false; } } 我要在这个类导入package com.isa.navi.jni.hmi; import android.content.Context; import android.os.Message; import android.os.StatFs; import android.util.Log; import androidx.annotation.NonNull; import com.isa.navi.jni.hmi.bean.UpdateList; import com.isa.navi.jni.hmi.update.USBListener; import com.isa.navi.library.map.UpdateEnvironment; import com.isa.navi.library.map.UpdateInfoBean; import com.isa.navi.manager.CallBackManager; import com.isa.navi.manager.CarManager; import com.isa.navi.manager.base.BaseHandlerManager; import com.isa.navi.receiver.USBReceiver; import com.isa.navi.utils.GsonUtils; import com.isa.navi.utils.LogUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.IOException; import java.time.LocalDate; import java.time.Month; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; public class HmiJNIImpl extends BaseHandlerManager implements IHmiJNI { private static final String TAG = "UPDATE"; private static final int MSG_DOWNLOAD_STATUS_CHANGE = 1; private final HmiProxyJNI mHmiProxyJNI; private final Format mFormat; private static final String PASSWORD_PREFIX = "DfCs"; private static final String PASSWORD_SUFFIX = "#@"; private static final int LAST_CHARS_LENGTH = 4; private static String updateUSBpath = ""; /** * 车辆管理实例,用于管理车辆相关的功能。 */ private CarManager mCarManager; private volatile static HmiJNIImpl mInstance; private boolean is_run = false; private final Set<String> USBPathSet = Collections.synchronizedSet(new HashSet<>()); public static HmiJNIImpl getInstance() { if (mInstance == null) { synchronized (HmiJNIImpl.class) { if (mInstance == null) { mInstance = new HmiJNIImpl(); } } } return mInstance; } private HmiJNIImpl() { super(true); mHmiProxyJNI = new HmiProxyJNI(); mFormat = Format.getInstance(); mCarManager = CarManager.getInstance(); } @Override public void initialize() { super.initialize(); LogUtils.d(TAG, "initialize : "); DfCert.getInstance().getService(); CallBackManager.getInstance().registerUSBEventChangeListener(new USBListener() { @Override public void path(String mountPath) { USBPathSet.add(mountPath); LogUtils.i(TAG,"USBPathSet:" + mountPath); } }); // 初始化C++模块 mHmiProxyJNI.InitializeCpp(); InstanceEngine(); } private int[] getCurrentYearAndQuarter() { int[] result = new int[2]; LocalDate currentDate = LocalDate.now(); // 获取当前年份 int currentYear = currentDate.getYear(); // 获取当前月份 Month currentMonth = currentDate.getMonth(); // 根据月份确定当前季度 int currentQuarter; switch (currentMonth) { case JANUARY: case FEBRUARY: case MARCH: currentQuarter = 1; break; case APRIL: case MAY: case JUNE: currentQuarter = 2; break; case JULY: case AUGUST: case SEPTEMBER: currentQuarter = 3; break; case OCTOBER: case NOVEMBER: case DECEMBER: currentQuarter = 4; break; default: currentQuarter = 0; } result[0] = currentYear; result[1] = currentQuarter; return result; } private int[] parseMapInfo(String mapInfo) { int[] result = new int[2]; // 检查输入字符串的长度是否为6(4位年份 + 2位季度) if (mapInfo == null || mapInfo.length() != 6) { LogUtils.e(TAG, "Input string must be in the format YYYYMM where YYYY is the year and MM is the quarter as a two-digit number."); return result; } // 提取年份(前4位) String yearStr = mapInfo.substring(0, 4); result[0] = Integer.parseInt(yearStr); // 提取季度(后2位),并验证它在1到4的范围内 String quarterStr = mapInfo.substring(4, 6); int quarter = Integer.parseInt(quarterStr); if (quarter < 1 || quarter > 4) { LogUtils.e(TAG, "Quarter must be between 1 and 4."); return result; } result[1] = quarter; return result; } public void dataVersionCheck() { Thread dataVersionCheckThread = new Thread(new Runnable() { @Override public void run() { try { UpdateInfoBean bean = new UpdateInfoBean(); String localVersion = mHmiProxyJNI.getMapInfo(); if(localVersion.isEmpty()) { bean.setUpdateStatus(4); handleDownloadStatusChange(bean); LogUtils.i(TAG, "Detected no updates for a long time"); return; } int[] currentYearAndQuarter = getCurrentYearAndQuarter(); int[] localYearAndQuarter = parseMapInfo(localVersion); int yearDifference = currentYearAndQuarter[0] - localYearAndQuarter[0]; int QuarterDifference = currentYearAndQuarter[1] - localYearAndQuarter[1]; if(yearDifference * 4 + QuarterDifference > 3) { bean.setUpdateStatus(4); handleDownloadStatusChange(bean); LogUtils.i(TAG, "Detected no updates for a long time"); } } catch (Exception e) { e.printStackTrace(); } } }); // 设置线程名称 dataVersionCheckThread.setName("ISA_NAVI_dataVersionCheck"); // 启动线程 dataVersionCheckThread.start(); } public void setContext(Context context) { if(mContext == null) { mContext = context; } language.getInstance().setContext(mContext); } @Override protected void handleMessage(Message msg) { switch (msg.what) { case MSG_DOWNLOAD_STATUS_CHANGE: handleDownloadStatusChange((String) msg.obj); break; default: break; } } private List<String> JsonArrayToListExample(JSONArray jsonArray) { List<String> stringList = new ArrayList<>(); try { // 遍历JSONArray for (int i = 0; i < jsonArray.length(); i++) { // 由于我们假设JSONArray只包含字符串,所以我们可以直接getString String item = jsonArray.getString(i); // 将字符串添加到列表中 stringList.add(item); } } catch (JSONException e) { e.printStackTrace(); } return stringList; } private UpdateInfoBean jsonToUpdateInfoBean(String json) { UpdateInfoBean result = null; try { // 解析整个JSON字符串为一个JSONObject JSONObject rootObject = new JSONObject(json); // 解析mUpdateMessage对象 JSONObject mUpdateMessage = rootObject.getJSONObject("mUpdateMessage"); String country = mUpdateMessage.getString("country"); double downloadSize = mUpdateMessage.getDouble("downloadSize"); boolean isCurrentCountry = mUpdateMessage.getBoolean("isCurrentCountry"); double progress = mUpdateMessage.getDouble("progress"); double totalSize = mUpdateMessage.getDouble("totalSize"); int updateStatus = mUpdateMessage.getInt("updateStatus"); String version = mUpdateMessage.getString("version"); // 解析mUpdateNotification对象 JSONObject mUpdateNotification = rootObject.getJSONObject("mUpdateNotification"); JSONArray updateException = mUpdateNotification.getJSONArray("UpdateException"); JSONArray updateFailedList = mUpdateNotification.getJSONArray("UpdateFailedList"); boolean updateResult = mUpdateNotification.getBoolean("UpdateResult"); JSONArray updateSuccessfulList = mUpdateNotification.getJSONArray("UpdateSuccessfulList"); // 解析mapStatus int mapStatus = rootObject.getInt("mapStatus"); UpdateInfoBean.UpdateNotification temp1 = new UpdateInfoBean.UpdateNotification(updateResult,JsonArrayToListExample(updateException),JsonArrayToListExample(updateSuccessfulList),JsonArrayToListExample(updateFailedList)); UpdateInfoBean.UpdateMessage temp2 = new UpdateInfoBean.UpdateMessage(country, version, totalSize, (int) progress, isCurrentCountry); temp2.setUpdateStatus(updateStatus); temp2.setDownloadSize(downloadSize); result = new UpdateInfoBean(mapStatus, temp1, temp2); } catch (Exception e) { LogUtils.e(TAG, "JSON parsing failed:" + e.toString()); } return result; } private void handleDownloadStatusChange(String json) { UpdateInfoBean bean = jsonToUpdateInfoBean(json); LogUtils.i(TAG, "handleDownloadStatusChange : " + bean); if (bean != null) { // 仅当status=8时检查is_run,其他状态直接放行 if(bean.getUpdateStatus() != 8 || is_run) { List<UpdateInfoBean> list = new ArrayList<>(); list.add(bean); CallBackManager.getInstance().notifyUpdateStatus(list); } } } private void handleDownloadStatusChange(UpdateInfoBean bean) { LogUtils.i(TAG, "handleDownloadStatusChange : " + bean); if (bean != null) { // 仅当status=8时检查is_run,其他状态直接放行 if(bean.getUpdateStatus() != 8 || is_run) { List<UpdateInfoBean> list = new ArrayList<>(); list.add(bean); CallBackManager.getInstance().notifyUpdateStatus(list); } } else { LogUtils.e(TAG, "UpdateInfoBean is null!"); } } public void sendUpdateMessage(String json) { LogUtils.d(TAG, "sendUpdateMessage : " + json); Message message = Message.obtain(); message.what = MSG_DOWNLOAD_STATUS_CHANGE; message.obj = json; mHandler.sendMessage(message); } @Override public void updateMap() { LogUtils.d(TAG, "activeUpdateStart : "); // 检查更新过程是否已经在运行,防止重复创建线程 if(is_run) { LogUtils.i(TAG, "更新程序已经在进行"); return; }else { is_run = true; } // 创建一个新线程来执行主动更新 Thread updateMapThread = new Thread(new Runnable() { @Override public void run() { try { // 调用JNI方法开始主动更新 mHmiProxyJNI.updateMap(); LogUtils.d(TAG, "activeUpdateStart end: "); } catch (Exception e) { e.printStackTrace(); } } }); // 设置线程名称 updateMapThread.setName("ISA_NAVI_UpdateMapThread"); // 启动线程 updateMapThread.start(); } public void updateMapend() { is_run = false; } @Override public void suspendUpdate(boolean suspend) { mHmiProxyJNI.suspendUpdate(suspend); } @Override public void cancelUpdate() { mHmiProxyJNI.cancelUpdate(); } /** * 启动USB检测线程,用于检测插入的U盘并判断是否有可用的升级文件。 */ public void startUSBDetection() { LogUtils.i(TAG, "startUSBDetection START"); // setUSBPath("/data/KVM_EU_202404_T1.2.zip"); Thread USBDetectionThread = new Thread(new Runnable(){ @Override public void run() { UpdateInfoBean bean = new UpdateInfoBean(); boolean isHaveUSBData = false; //遍历检测到的U盘路径 if(USBPathSet.isEmpty()) { //未检测到U盘,触发提示弹窗 LogUtils.e(TAG, "No USB drive detected!"); bean.setUpdateStatus(2); handleDownloadStatusChange(bean); return; } int set_num = 0; for(String usbPath : USBPathSet ) { //判断U盘路径是否真实存在 set_num ++; if(USBReceiver.isMounted(usbPath)) { File usbFile = new File(usbPath); File[] listFiles = usbFile.listFiles(); if(listFiles == null) { continue; } File newfile = null; for(File file : listFiles) { //判断U盘内是否含有升级文件 if(!file.isDirectory() && mFormat.isUpgradeFileNamingFormat(file.getName())) { isHaveUSBData = true; if(newfile == null) { newfile = file; } else { if(Format.getInstance().isNewerVersion(file.getName().replaceAll("\\.\\w+$", ""), newfile.getName().replaceAll("\\.\\w+$", ""))) { newfile = file; } } } } //未检测到U盘指定路径下是否有数据,触发提示弹窗 if(!isHaveUSBData || newfile == null) { LogUtils.e(TAG, "The USB drive does not contain an upgrade package!"); bean.setUpdateStatus(3); handleDownloadStatusChange(bean); return; }else{ // 从文件名中提取版本号 String localDataPath = Format.getInstance().extractVersion(getCountryDbPath()); LogUtils.i(TAG, "file name:" + newfile.getName()); LogUtils.i(TAG, "localDataPath:" + localDataPath); if(localDataPath.isEmpty()) { String mapinfo = getMapInfo(); if(!mapinfo.isEmpty()) { String[] newVersionParts = new String[2]; Format.getInstance().extractVersion(newfile.getName().replaceAll("\\.\\w+$", ""), newVersionParts); String newUpdateVersion = newVersionParts[0]; String newReleasesVersion = newVersionParts[1]; LogUtils.i(TAG, "localDataPath.isEmpty() newUpdateVersion: " + newUpdateVersion); LogUtils.i(TAG, "localDataPath.isEmpty() newReleasesVersion: " + newReleasesVersion); if(Integer.parseInt(newUpdateVersion) > Integer.parseInt(mapinfo) || (Integer.parseInt(newUpdateVersion) == Integer.parseInt(mapinfo) && Double.parseDouble(newReleasesVersion) > 1)) { LogUtils.i(TAG,"Trigger USB drive update!"); bean.setUpdateStatus(0); handleDownloadStatusChange(bean); //设置U盘更新路径 updateUSBpath = usbPath; setUSBPath(newfile.getAbsolutePath()); LogUtils.i(TAG, "filePath:" + newfile.getAbsolutePath()); } else { LogUtils.e(TAG, "The upgrade package version on the USB drive is less than or equal to the vehicle's version!"); bean.setUpdateStatus(1); handleDownloadStatusChange(bean); } } else { LogUtils.i(TAG,"Trigger USB drive update!"); bean.setUpdateStatus(0); handleDownloadStatusChange(bean); //设置U盘更新路径 updateUSBpath = usbPath; setUSBPath(newfile.getAbsolutePath()); LogUtils.i(TAG, "filePath:" + newfile.getAbsolutePath()); } return; } // 判断U盘内数据版本是否大于车机数据版本 if(Format.getInstance().isNewerVersion(newfile.getName().replaceAll("\\.\\w+$", ""), localDataPath)) { LogUtils.i(TAG,"Trigger USB drive update!"); bean.setUpdateStatus(0); handleDownloadStatusChange(bean); //设置U盘更新路径 updateUSBpath = usbPath; setUSBPath(newfile.getAbsolutePath()); LogUtils.i(TAG, "filePath:" + newfile.getAbsolutePath()); } else { LogUtils.e(TAG, "The upgrade package version on the USB drive is less than or equal to the vehicle's version!"); bean.setUpdateStatus(1); handleDownloadStatusChange(bean); } return; } } else { if(set_num == USBPathSet.size()) { //未检测到U盘,触发提示弹窗 LogUtils.e(TAG, "No USB drive detected!"); bean.setUpdateStatus(2); handleDownloadStatusChange(bean); return; } } } } }); USBDetectionThread.setName("ISA_NAVI_USBDetectionThread"); USBDetectionThread.start(); } public String getMapInfo() { String result = mHmiProxyJNI.getMapInfo(); LogUtils.i(TAG,"MapInfo:" + result); return result; } public String getUpdateVersion() { String result = mHmiProxyJNI.getUpdateVersion(); LogUtils.i(TAG,"UpdateVersion:" + result); return result; } public UpdateEnvironment checkUpdateEnvironment() { String json = mHmiProxyJNI.checkUpdateEnvironment(); LogUtils.d(TAG,"checkUpdateEnvironment JSON:" + json); UpdateEnvironment result = GsonUtils.fromJson(json, UpdateEnvironment.class); if(result == null) { LogUtils.e(TAG, "GsonUtils.fromJson(json, UpdateEnvironment.class) Fail!"); return null; } if (!result.getResult()) { List<String> temp_list = new ArrayList<>(); for (int i : result.getInt_reason()) { String str = language.getInstance().getEnvironment(i); if(str != null && !str.isEmpty()) { temp_list.add(str); } } // 更新temp对象中的reason字段 result.setReason(temp_list); } LogUtils.i(TAG,"checkUpdateEnvironment :" + result); return result; } public String getUpdatePurpose() { return language.getInstance().getUpdatePurpose(); } public String getUpdateContent() { return language.getInstance().getUpdateContent(); } public String getUserManual() { return language.getInstance().getUserManual(); } public String getUpdatedContentDescription() { return language.getInstance().getUpdatedContentDescription(); } public int getEstimatedTime() { return 30; } private void InstanceEngine() { Thread InstanceEngine = new Thread(new Runnable(){ @Override public void run() { LogUtils.d("ISA_NAVI", "InstanceEngine start!"); mHmiProxyJNI.instanceEngine(); } }); InstanceEngine.setName("ISA_NAVI_InstanceEngine"); InstanceEngine.start(); } // 获取后四位字符 @NonNull private static String getLastFourChars(String mapInfo) { if (mapInfo == null || mapInfo.isEmpty()) { LogUtils.e(TAG, "mapInfo cannot be null or empty"); return "0000"; } return mapInfo.length() >= LAST_CHARS_LENGTH ? mapInfo.substring(mapInfo.length() - LAST_CHARS_LENGTH) : "0000"; } // 生成密码 @NonNull private String generatePassword() { String mapInfo = getMapInfo(); String lastFourChars = getLastFourChars(mapInfo); return PASSWORD_PREFIX + lastFourChars + PASSWORD_SUFFIX; } // 校验密码 public boolean validatePassword(String inputPassword) { if (inputPassword == null) { return false; } String generatedPassword = generatePassword(); LogUtils.i(TAG, "generatedPassword:" + generatedPassword); LogUtils.i(TAG, "inputPassword:" + inputPassword); return inputPassword.equals(generatedPassword); } public void setUSBPath(String USBPath) { mHmiProxyJNI.setUSBPath(USBPath); } public boolean unzipFile(String zipFilePath, String destinationDirPath) { return ZipUtils.getInstance().unzip(zipFilePath, destinationDirPath); } public long getFileSize(String filePath) { File file = new File(filePath); if(!file.isFile() || !file.exists()) { return 0; } LogUtils.d(TAG, "getFileSize:" + file.length()); return file.length(); } public long getAvailableSpace(String filePath) { StatFs stat = new StatFs(filePath); long availableBlocks = stat.getAvailableBlocksLong(); long blockSize = stat.getBlockSizeLong(); LogUtils.i(TAG, "[AvailableSpace]:" + availableBlocks * blockSize + "字节"); return availableBlocks * blockSize; } public String getFail(int i) { return language.getInstance().getFail(i); } public boolean decryptFile(String encryptedFilePath, String decryptedFilePath) { return new DecryptUtil().decryptFile(encryptedFilePath, decryptedFilePath, DfCert.getInstance().getKEY_AES_256()); } public boolean verifySignature(String filePath, String signFilePath) { try { return DecryptUtil.verifySignature(filePath, signFilePath, DfCert.getInstance().getPUBLIC_KEY()); } catch (Exception e) { return false; } } /** * 获取高压电池电量百分比。 * * 此方法通过调用mCarManager.getHVPercent来获取高压电池的电量百分比。如果调用成功,则返回电量百分比值; * 如果调用失败或发生异常,则捕获异常并打印堆栈跟踪,最后返回0。 * * @return 一个浮点数,表示高压电池的电量百分比(0-100);如果获取失败或发生异常,则返回0。 */ public float getHVPercent() { float HVPercent = 0; try { HVPercent = mCarManager.getHVPercent(); if(HVPercent > 100 || HVPercent < 0) { HVPercent = 0; } } catch (Exception e) { e.printStackTrace(); } return HVPercent; } boolean isMounted() { return USBReceiver.isMounted(updateUSBpath); } public String getCountryDbPath() { return mHmiProxyJNI.getCountryDbPath(); } public String get_Global_m_data_address() { return mHmiProxyJNI.get_Global_m_data_address(); } public boolean dataVerification(String verifyDataPath) { LogUtils.i(TAG, "dataVerification[verifyDataPath]:" + verifyDataPath); String signPath = get_Global_m_data_address() + "sign/"; if(!mapControl()) { return false; } //解压加密数据 LogUtils.i(TAG, "verifyDataPath[" + verifyDataPath + "] -> signPath[" + signPath + "]"); if(!unzipFile(verifyDataPath, signPath)) { //删除解密验签中间文件 if(!deleteDirectory(signPath)) { LogUtils.e(TAG, "无法删除解密验签中间文件!"); } return false; } if(!mapControl()) { return false; } //提取签名文件以及加密文件的绝对路径 String[] temp = ZipUtils.getInstance().findEncryptedZipFiles(signPath); String aesDaraPath = temp[1]; String signDataPtah = temp[0]; LogUtils.i(TAG, "aesDaraPath:" + aesDaraPath); LogUtils.i(TAG, "signDataPtah" + signDataPtah); if(!mapControl()) { return false; } //验证签名 if(!verifySignature(aesDaraPath, signDataPtah)) { LogUtils.e(TAG, "verifySignature fail!"); //删除解密验签中间文件 if(!deleteDirectory(signPath)) { LogUtils.e(TAG, "无法删除解密验签中间文件!"); } return false; } if(!mapControl()) { return false; } //对称解密Zip if(!decryptFile(aesDaraPath, verifyDataPath)) { LogUtils.e(TAG, "decryptFile fail!"); //删除解密验签中间文件 if(!deleteDirectory(signPath)) { LogUtils.e(TAG, "无法删除解密验签中间文件!"); } return false; } //删除解密验签中间文件 if(!deleteDirectory(signPath)) { LogUtils.e(TAG, "无法删除解密验签中间文件!"); } LogUtils.i(TAG, "dataVerification success"); return true; } /** * 删除指定目录及其所有内容 * * @param directory 指定的目录路径 * @return 如果删除成功返回 true,否则返回 false */ public boolean deleteDirectory(String directory) { File dir = new File(directory); if (!dir.exists()) { LogUtils.e("目录不存在: " + directory); return false; // 目录不存在,视为删除失败 } if (!dir.isDirectory()) { LogUtils.e("指定路径不是一个目录: " + directory); return false; // 路径不是目录,无法删除 } return deleteRecursive(dir); // 递归删除目录 } /** * 递归删除文件或目录 * * @param file 文件或目录 * @return 如果删除成功返回 true,否则返回 false */ private boolean deleteRecursive(File file) { if (file.isDirectory()) { // 如果是目录,递归删除其所有子文件和子目录 File[] files = file.listFiles(); if (files != null) { for (File subFile : files) { if (!deleteRecursive(subFile)) { return false; // 如果某个子文件或子目录删除失败,则整体失败 } } } } // 删除当前文件或空目录 if (!file.delete()) { LogUtils.e("无法删除文件或目录: " + file.getAbsolutePath()); return false; // 删除失败 } LogUtils.i("已成功删除: " + file.getAbsolutePath()); return true; // 删除成功 } public boolean mapControl() { LogUtils.d(TAG, "mapControl JAVA start"); return mHmiProxyJNI.mapControl(); } public boolean zipDbFiles(String sourceDir, String outputZipPath) { return ZipUtils.getInstance().zipDbFiles(sourceDir, outputZipPath); } public boolean zip(String sourcePath, String outputZipPath) { return ZipUtils.getInstance().zip(sourcePath, outputZipPath, true); } // Used to load the 'native-lib' library on application startup. static { LogUtils.d(TAG, "loadLibrary IsaEngineJni " + System.currentTimeMillis()); System.loadLibrary("IsaEngineJni"); } }

using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; [assembly: CommandClass(typeof(ArchitectureCADPlugin.Commands))] [assembly: CommandClass(typeof(ArchitectureCADPlugin.Loader))] namespace ArchitectureCADPlugin { public class Commands { // 存储识别的图层名称 private static string axisLayer = ""; private static string axisNumberLayer = ""; private static string dimensionLayer = ""; private static string beamLayer = ""; private static string columnLayer = ""; private static string wallLayer = ""; private static string cavityLayer = ""; // AXISID -> AID [CommandMethod("AID", CommandFlags.Modal)] public void IdentifyAxis() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 点选识别轴网 PromptEntityResult perAxis = ed.GetEntity("\n【轴网识别】请点选轴网图层中的对象: "); if (perAxis.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity entAxis = tr.GetObject(perAxis.ObjectId, OpenMode.ForRead) as Entity; if (entAxis != null) { axisLayer = entAxis.Layer; ed.WriteMessage($"\n已识别轴网图层: {axisLayer}"); } // 点选识别轴号 PromptEntityResult perAxisNum = ed.GetEntity("\n【轴网识别】请点选轴号图层中的对象: "); if (perAxisNum.Status == PromptStatus.OK) { Entity entAxisNum = tr.GetObject(perAxisNum.ObjectId, OpenMode.ForRead) as Entity; if (entAxisNum != null) { axisNumberLayer = entAxisNum.Layer; ed.WriteMessage($"\n已识别轴号图层: {axisNumberLayer}"); } } // 点选识别标注尺寸 PromptEntityResult perDim = ed.GetEntity("\n【轴网识别】请点选标注尺寸图层中的对象: "); if (perDim.Status == PromptStatus.OK) { Entity entDim = tr.GetObject(perDim.ObjectId, OpenMode.ForRead) as Entity; if (entDim != null) { dimensionLayer = entDim.Layer; ed.WriteMessage($"\n已识别标注尺寸图层: {dimensionLayer}"); } } tr.Commit(); } SaveLayerSettings(); ed.WriteMessage("\n轴网识别完成!"); } catch (Exception ex) { ed.WriteMessage($"\n轴网识别错误: {ex.Message}"); } } // BEAMSTAT -> BST [CommandMethod("BST", CommandFlags.Modal)] public void BeamStatistics() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { if (string.IsNullOrEmpty(beamLayer)) { ed.WriteMessage("\n【梁统计】请先使用 BID 命令识别梁线图层!"); return; } // 获取选择集 PromptSelectionResult psr = ed.GetSelection(); if (psr.Status != PromptStatus.OK) return; Dictionary<string, int> beamCountDict = new Dictionary<string, int>(); Dictionary<string, int> sectionCountDict = new Dictionary<string, int>(); using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (ObjectId objId in psr.Value.GetObjectIds()) { Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null && ent.Layer == beamLayer) { string beamName = ExtractBeamName(ent); string sectionSize = ExtractSectionSize(ent); if (!string.IsNullOrEmpty(beamName)) { beamCountDict[beamName] = beamCountDict.ContainsKey(beamName) ? beamCountDict[beamName] + 1 : 1; } if (!string.IsNullOrEmpty(sectionSize)) { sectionCountDict[sectionSize] = sectionCountDict.ContainsKey(sectionSize) ? sectionCountDict[sectionSize] + 1 : 1; } } } // 创建统计表格 CreateBeamStatisticsTable(beamCountDict, sectionCountDict, tr); tr.Commit(); } } catch (Exception ex) { ed.WriteMessage($"\n梁统计错误: {ex.Message}"); } } // BEAMID -> BID [CommandMethod("BID", CommandFlags.Modal)] public void IdentifyBeamLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { PromptEntityResult per = ed.GetEntity("\n【梁识别】请点选梁线图层中的对象: "); if (per.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { beamLayer = ent.Layer; ed.WriteMessage($"\n已识别梁线图层: {beamLayer}"); SaveLayerSettings(); } tr.Commit(); } } catch (Exception ex) { ed.WriteMessage($"\n梁识别错误: {ex.Message}"); } } // COLUMNID -> CID [CommandMethod("CID", CommandFlags.Modal)] public void IdentifyColumnLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { PromptEntityResult per = ed.GetEntity("\n【柱识别】请点选柱图层中的对象: "); if (per.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { columnLayer = ent.Layer; ed.WriteMessage($"\n已识别柱图层: {columnLayer}"); SaveLayerSettings(); } tr.Commit(); } } catch (Exception ex) { ed.WriteMessage($"\n柱识别错误: {ex.Message}"); } } // WALLID -> WID [CommandMethod("WID", CommandFlags.Modal)] public void IdentifyWallLayer() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { PromptEntityResult per = ed.GetEntity("\n【墙识别】请点选墙图层中的对象: "); if (per.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity; if (ent != null) { wallLayer = ent.Layer; ed.WriteMessage($"\n已识别墙图层: {wallLayer}"); SaveLayerSettings(); } tr.Commit(); } } catch (Exception ex) { ed.WriteMessage($"\n墙识别错误: {ex.Message}"); } } // EXPORTBEAM -> EB [CommandMethod("EB", CommandFlags.Modal)] public void ExportBeamToExcel() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; try { PromptSelectionResult psr = ed.GetSelection("\n【导出梁表】请选择梁统计表格: "); if (psr.Status != PromptStatus.OK || psr.Value.Count == 0) return; using (Transaction tr = doc.Database.TransactionManager.StartTransaction()) { Table table = tr.GetObject(psr.Value[0].ObjectId, OpenMode.ForRead) as Table; if (table != null) { ExportTableToCSV(table); } tr.Commit(); } } catch (Exception ex) { ed.WriteMessage($"\n导出错误: {ex.Message}"); } } // LOADSETTINGS -> LS [CommandMethod("LS", CommandFlags.Modal)] public void LoadLayerSettings() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; try { axisLayer = Application.GetSystemVariable("AXIS_LAYER") as string ?? ""; axisNumberLayer = Application.GetSystemVariable("AXIS_NUM_LAYER") as string ?? ""; dimensionLayer = Application.GetSystemVariable("DIM_LAYER") as string ?? ""; beamLayer = Application.GetSystemVariable("BEAM_LAYER") as string ?? ""; columnLayer = Application.GetSystemVariable("COLUMN_LAYER") as string ?? ""; wallLayer = Application.GetSystemVariable("WALL_LAYER") as string ?? ""; cavityLayer = Application.GetSystemVariable("CAVITY_LAYER") as string ?? ""; ed.WriteMessage("\n已加载图层设置:"); ed.WriteMessage($"\n轴网图层: {axisLayer}"); ed.WriteMessage($"\n轴号图层: {axisNumberLayer}"); ed.WriteMessage($"\n标注尺寸图层: {dimensionLayer}"); ed.WriteMessage($"\n梁线图层: {beamLayer}"); ed.WriteMessage($"\n柱图层: {columnLayer}"); ed.WriteMessage($"\n墙图层: {wallLayer}"); } catch (Exception ex) { ed.WriteMessage($"\n加载设置错误: {ex.Message}"); } } // SHOWSETTINGS -> SS [CommandMethod("SS", CommandFlags.Modal)] public void ShowLayerSettings() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; ed.WriteMessage("\n当前图层设置:"); ed.WriteMessage($"\n轴网图层: {axisLayer}"); ed.WriteMessage($"\n轴号图层: {axisNumberLayer}"); ed.WriteMessage($"\n标注尺寸图层: {dimensionLayer}"); ed.WriteMessage($"\n梁线图层: {beamLayer}"); ed.WriteMessage($"\n柱图层: {columnLayer}"); ed.WriteMessage($"\n墙图层: {wallLayer}"); ed.WriteMessage($"\n空洞图层: {cavityLayer}"); } private void SaveLayerSettings() { Application.SetSystemVariable("AXIS_LAYER", axisLayer); Application.SetSystemVariable("AXIS_NUM_LAYER", axisNumberLayer); Application.SetSystemVariable("DIM_LAYER", dimensionLayer); Application.SetSystemVariable("BEAM_LAYER", beamLayer); Application.SetSystemVariable("COLUMN_LAYER", columnLayer); Application.SetSystemVariable("WALL_LAYER", wallLayer); Application.SetSystemVariable("CAVITY_LAYER", cavityLayer); } private string ExtractBeamName(Entity ent) { // 实际项目中应根据具体需求完善此方法 if (ent is DBText text && !string.IsNullOrWhiteSpace(text.TextString)) return text.TextString.Trim(); if (ent is MText mtext && !string.IsNullOrWhiteSpace(mtext.Text)) return mtext.Text.Trim(); return ""; } private string ExtractSectionSize(Entity ent) { // 实际项目中应根据具体需求完善此方法 if (ent is DBText text) { string textValue = text.TextString.Trim(); if (textValue.Contains("x") || textValue.Contains("×")) return textValue; } if (ent is MText mtext) { string textValue = mtext.Text.Trim(); if (textValue.Contains("x") || textValue.Contains("×")) return textValue; } return ""; } private void CreateBeamStatisticsTable( Dictionary<string, int> beamCountDict, Dictionary<string, int> sectionCountDict, Transaction tr) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; // 获取表格插入点 PromptPointResult ppr = ed.GetPoint("\n【梁统计】请指定表格插入点: "); if (ppr.Status != PromptStatus.OK) return; // 准备统计项 List<BeamStatItem> statItems = new List<BeamStatItem>(); // 添加梁名称统计项 foreach (var pair in beamCountDict) { statItems.Add(new BeamStatItem { Name = pair.Key, SectionSize = ExtractSectionFromName(pair.Key), Count = pair.Value }); } // 添加截面尺寸统计项 foreach (var pair in sectionCountDict) { statItems.Add(new BeamStatItem { Name = "", SectionSize = pair.Key, Count = pair.Value }); } // 计算截面面积和荷载 foreach (var item in statItems) { if (!string.IsNullOrEmpty(item.SectionSize)) { (double width, double height) = ParseSectionSize(item.SectionSize); if (width > 0 && height > 0) { // 计算截面面积 (mm² 转换为 m²) item.Area = (width * height) / 1000000.0; // 计算集中线荷载 (kN/m) // 公式: $ Load = Area \times Density$ // 假设混凝土密度为 25 kN/m³ item.Load = item.Area * 25; } } } // 按荷载排序 statItems = statItems .Where(i => i.Load > 0) .OrderByDescending(i => i.Load) .ToList(); // 创建表格 Table table = new Table { TableStyle = db.Tablestyle, Position = ppr.Value }; // 设置表格尺寸 (行数 = 标题行 + 表头行 + 数据行) table.SetSize(statItems.Count + 2, 6); // 设置列宽 table.Columns[0].Width = 80; // 序号 table.Columns[1].Width = 150; // 梁名称 table.Columns[2].Width = 120; // 截面尺寸 table.Columns[3].Width = 80; // 数量 table.Columns[4].Width = 120; // 截面面积 table.Columns[5].Width = 150; // 集中线荷载 // 设置标题行 table.Cells[0, 0].Value = "梁截面尺寸汇总表"; table.Cells[0, 0].Alignment = CellAlignment.MiddleCenter; table.Cells[0, 0].TextHeight = 5.0; table.MergeCells(CellRange.Create(table, 0, 0, 0, 5)); // 设置表头 string[] headers = { "序号", "梁名称", "梁截面尺寸(mm)", "数量", "截面面积(㎡)", "集中线荷载(kN/m)" }; for (int i = 0; i < headers.Length; i++) { table.Cells[1, i].Value = headers[i]; table.Cells[1, i].Alignment = CellAlignment.MiddleCenter; table.Cells[1, i].TextHeight = 3.5; } // 填充数据行 for (int i = 0; i < statItems.Count; i++) { var item = statItems[i]; table.Cells[i + 2, 0].Value = (i + 1).ToString(); // 序号 table.Cells[i + 2, 1].Value = item.Name; // 梁名称 table.Cells[i + 2, 2].Value = item.SectionSize; // 截面尺寸 table.Cells[i + 2, 3].Value = item.Count.ToString(); // 数量 table.Cells[i + 2, 4].Value = item.Area.ToString("F6");// 截面面积 table.Cells[i + 2, 5].Value = item.Load.ToString("F2");// 集中线荷载 // 设置单元格样式 for (int j = 0; j < 6; j++) { table.Cells[i + 2, j].Alignment = CellAlignment.MiddleCenter; table.Cells[i + 2, j].TextHeight = 3.0; } } // 将表格添加到模型空间 BlockTableRecord btr = tr.GetObject( db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; btr.AppendEntity(table); tr.AddNewlyCreatedDBObject(table, true); ed.WriteMessage("\n【梁统计】已生成梁统计表格"); } private void ExportTableToCSV(Table table) { try { SaveFileDialog saveDlg = new SaveFileDialog { Title = "导出梁统计表格", Filter = "CSV文件|*.csv", FileName = "梁截面尺寸汇总表.csv" }; if (saveDlg.ShowDialog() != DialogResult.OK) return; string filePath = saveDlg.FileName; if (!filePath.EndsWith(".csv", StringComparison.OrdinalIgnoreCase)) filePath += ".csv"; StringBuilder csv = new StringBuilder(); csv.AppendLine("序号,梁名称,梁截面尺寸(mm),数量,截面面积(㎡),集中线荷载(kN/m)"); // 从第2行开始(跳过标题行和表头行) for (int row = 2; row < table.Rows.Count; row++) { List<string> rowData = new List<string>(); for (int col = 0; col < table.Columns.Count; col++) { string value = table.Cells[row, col].Value?.ToString() ?? ""; rowData.Add(value.Contains(",") ? $"\"{value}\"" : value); } csv.AppendLine(string.Join(",", rowData)); } File.WriteAllText(filePath, csv.ToString(), Encoding.UTF8); Application.ShowAlertDialog($"表格已成功导出到:\n{filePath}"); } catch (Exception ex) { Application.ShowAlertDialog($"导出错误:\n{ex.Message}"); } } private string ExtractSectionFromName(string beamName) { // 从梁名称中提取截面尺寸 (实际项目应完善此逻辑) if (beamName.Contains("-")) { string[] parts = beamName.Split('-'); if (parts.Length > 1) { string lastPart = parts[parts.Length - 1].Trim(); if (lastPart.Contains("x") || lastPart.Contains("×")) return lastPart; } } return ""; } private (double width, double height) ParseSectionSize(string sectionSize) { // 解析截面尺寸字符串 (如 "200x500") try { string cleanSize = sectionSize .Replace("×", "x") .Replace(" ", "") .Replace("mm", "") .Trim(); string[] parts = cleanSize.Split('x', 'X'); if (parts.Length == 2 && double.TryParse(parts[0], out double width) && double.TryParse(parts[1], out double height)) { return (width, height); } } catch { // 忽略解析错误 } return (0, 0); } } public class BeamStatItem { public string Name { get; set; } = ""; public string SectionSize { get; set; } = ""; public int Count { get; set; } = 0; public double Area { get; set; } = 0; public double Load { get; set; } = 0; } public class Loader { [CommandMethod("LOADARCHPLUGIN", CommandFlags.Modal)] public void LoadPlugin() { Application.ShowAlertDialog("建筑CAD识别与标注插件已加载!"); } } } CS0234命名空间“System.Windows”中不存在类型或命名空间名“Forms”(是否缺少程序集引用?) CS0104“Exception”是Autodesk.AutoCAD.Runtime.Exception"和System.Exception”之间的不明确的引用 CS0104“Exception”是Autodesk.AutoCAD.Runtime.Exception”和“System.Exception”之间的不明确的引用 CS0104“Exception”是Autodesk.AutoCAD.Runtime.Exception"和System.Exception"之间的不明确的引用 CS0104“Exception"是"Autodesk.AutoCAD.Runtime.Exception”和“System.Exception"之间的不明确的引用 CS0104“Exception”是Autodesk.AutoCAD.Runtime.Exception”和System.Exception"之间的不明确的引用 CS1503参数1:无法从“string转换为“Autodesk.AutoCAD.Editorlnput.PromptSelectionOptions' CS0104“Exception”是Autodesk.AutoCAD.Runtime.Exception"和System.Exception"之间的不明确的引用 CS0104“Exception"是"Autodesk.AutoCAD.Runtime.Exception"和System.Exception"之间的不明确的引用 CS7036未提供与“SaveFileDialog.SaveFileDialog(string, string,string,string,SaveFileDialog.SaveFileDialogFlags)"的所需参数"title"对应的参数 CS0117“SaveFileDialog"未包含“Title”的定义 CS0117“SaveFileDialog"未包含Filter"的定义 CS0117“SaveFileDialog"未包含“FileName”的定义 CS0012 类型"DialogResult"在未引用的程序集中定义。必须添加对程序集"System.Windows.Forms, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"的引用。 CS1061“SaveFileDialog"未包含“FileName”的定义,并且找不到可接受第一个“SaveFileDialog"类型参数的可访问扩展方法“FileName”(是否缺少using 指令或程序集引用?) CS0104“Exception”是Autodesk.AutoCAD.Runtime.Exception"和System.Exception"之间的不明确的引用

package com.example.test1.service; import com.example.test1.component.WordToHtmlConverter; import com.jcraft.jsch.; import org.apache.poi.xwpf.usermodel.; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.; import java.nio.file.; import java.util.UUID; @Service public class FileProcessingService { // 远程服务器配置 private static final String REMOTE_HOST = “”; private static final int REMOTE_PORT = ; private static final String REMOTE_USER = “”; private static final String REMOTE_PASSWORD = “#”; private static final String REMOTE_BASE_DIR = “////”; private static final String BASE_URL = “/images/”; private static final String LOCAL_TEMP_DIR = System.getProperty(“java.io.tmpdir”) + “/service_files/”; public String processInput(Object input) throws Exception { if (input instanceof String) { return processText((String) input); } else if (input instanceof MultipartFile) { return processFile((MultipartFile) input); } throw new IllegalArgumentException(“Unsupported input type”); } private String processText(String text) { // 转义HTML特殊字符 String escapedText = escapeHtml(text); // 保留换行符 - 将换行符转换为 标签 String withBreaks = escapedText.replace(“\n”, “ ”); // 直接返回HTML内容 return “ ” + withBreaks + “ ”; } private String processFile(MultipartFile file) throws Exception { String originalName = file.getOriginalFilename(); if (originalName == null) throw new IllegalArgumentException(“Invalid file name”); String extension = originalName.substring(originalName.lastIndexOf(“.”) + 1).toLowerCase(); switch (extension) { case “jpg”: case “jpeg”: case “png”: case “gif”: // 生成包含图片引用的HTML String imageUrl = uploadImage(file.getBytes(), extension); return “Service Image”; case “doc”: case “docx”: // 转换Word文档为HTML return convertToHtml(file.getInputStream()); default: throw new IllegalArgumentException(“Unsupported file type: " + extension); } } /** * 上传图片到远程服务器 * @param imageData 图片字节数组 * @param extension 文件扩展名 * @return 图片URL */ public String uploadImage(byte[] imageData, String extension) throws Exception { String fileName = “img_” + UUID.randomUUID() + “.” + extension; Path tempPath = saveTempFile(imageData, fileName); uploadViaSftp(tempPath, fileName); return BASE_URL + fileName; } private void uploadViaSftp(Path localPath, String remoteFileName) throws Exception { JSch jsch = new JSch(); Session session = jsch.getSession(REMOTE_USER, REMOTE_HOST, REMOTE_PORT); session.setPassword(REMOTE_PASSWORD); session.setConfig(“StrictHostKeyChecking”, “no”); session.connect(); ChannelSftp channel = (ChannelSftp) session.openChannel(“sftp”); channel.connect(); // 确保远程目录存在 try { channel.cd(REMOTE_BASE_DIR); } catch (SftpException e) { channel.mkdir(REMOTE_BASE_DIR); channel.cd(REMOTE_BASE_DIR); } // 上传文件 channel.put(localPath.toString(), remoteFileName); // 清理本地文件 Files.deleteIfExists(localPath); channel.disconnect(); session.disconnect(); } private Path saveTempFile(byte[] data, String fileName) throws IOException { Path dirPath = Paths.get(LOCAL_TEMP_DIR); if (!Files.exists(dirPath)) { Files.createDirectories(dirPath); } Path filePath = dirPath.resolve(fileName); Files.write(filePath, data); return filePath; } public String convertToHtml(InputStream docxStream) throws Exception { try (XWPFDocument document = new XWPFDocument(docxStream)) { StringBuilder htmlBuilder = new StringBuilder(); htmlBuilder.append(”“); // 处理段落 for (XWPFParagraph paragraph : document.getParagraphs()) { htmlBuilder.append(processParagraph(paragraph)); } // 处理表格 for (XWPFTable table : document.getTables()) { htmlBuilder.append(processTable(table)); } htmlBuilder.append(”“); return htmlBuilder.toString(); } } private String processParagraph(XWPFParagraph paragraph) throws Exception { StringBuilder paraBuilder = new StringBuilder(); boolean isFirstRun = true; for (XWPFRun run : paragraph.getRuns()) { String text = run.getText(0); // 处理图片 if (run.getEmbeddedPictures().size() > 0) { for (XWPFPicture picture : run.getEmbeddedPictures()) { XWPFPictureData picData = picture.getPictureData(); // 上传图片并获取URL String imageUrl = uploadImage( picData.getData(), picData.suggestFileExtension() ); paraBuilder.append(”“); } } if (text != null && !text.trim().isEmpty()) { // 处理换行符 String processedText = text.replace(”\n", “ ”); // 处理文本样式 if (run.isBold()) paraBuilder.append(“”); if (run.isItalic()) paraBuilder.append(“”); paraBuilder.append(escapeHtml(processedText)); if (run.isItalic()) paraBuilder.append(“”); if (run.isBold()) paraBuilder.append(“”); } // 检测换行符(Word中的硬回车) if (run.getCTR().getBrArray().length > 0) { paraBuilder.append(“ ”); } isFirstRun = false; } // 如果是空段落,保留换行效果 if (paraBuilder.length() == 0) { return “ ”; } return “ ” + paraBuilder.toString() + “ ”; } private String processTable(XWPFTable table) throws Exception { StringBuilder tableBuilder = new StringBuilder(“”); for (XWPFTableRow row : table.getRows()) { tableBuilder.append(“”); for (XWPFTableCell cell : row.getTableCells()) { tableBuilder.append(“”); for (XWPFParagraph para : cell.getParagraphs()) { tableBuilder.append(processParagraph(para)); } tableBuilder.append(“”); } tableBuilder.append(“”); } tableBuilder.append(“”); return tableBuilder.toString(); } private String escapeHtml(String text) { return text.replace(“&”, “&”) .replace(“<”, “<”) .replace(“>”, “>”) .replace(“"”, “"”) .replace(“'”, “'”); } }修改之前的解决方案,支持文体和图片同时传入,且图片支持多图片传入,转为HTML。保留word上传转为HTML功能。图片都存入服务器

winform中以下代码可以帮我整合成一个类供给主程序调用。目前只支持5个串口和5个modubusRTU主站的通讯读写后续可能还要增加多个这种设备。using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using EasyModbus; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button; namespace 多个串口类 { public partial class Form1 : Form { static ModbusClient modbusrtu0 = new ModbusClient("COM1"); static ModbusClient modbusrtu1 = new ModbusClient("COM2"); static ModbusClient modbusrtu2 = new ModbusClient("COM3"); static ModbusClient modbusrtu3 = new ModbusClient("COM4"); static ModbusClient modbusrtu4 = new ModbusClient("COM5"); static ModbusClient modbusrtu5 = new ModbusClient("COM6"); static ModbusClient modbusrtu6 = new ModbusClient("COM7"); static ModbusClient modbusrtu7 = new ModbusClient("COM8"); static ModbusClient modbusrtu8 = new ModbusClient("COM9"); static ModbusClient modbusrtu9 = new ModbusClient("COM10"); private Thread modbusThread0; private Thread modbusThread1; private Thread modbusThread2; private Thread modbusThread3; private Thread modbusThread4; private Thread modbusThread5; private Thread modbusThread6; private Thread modbusThread7; private Thread modbusThread8; private Thread modbusThread9; int[] modbusRtuInt_0=new int[1000]; int[] modbusRtuInt_1 = new int[1000]; int[] modbusRtuInt_2 = new int[1000]; int[] modbusRtuInt_3 = new int[1000]; int[] modbusRtuInt_4 = new int[1000]; SerialPort sPort_0; SerialPort sPort_1; SerialPort sPort_2; SerialPort sPort_3; SerialPort sPort_4; SerialPort sPort_5; SerialPort sPort_6; SerialPort sPort_7; SerialPort sPort_8; SerialPort sPort_9; private StringBuilder receivedDataBuffer0 = new StringBuilder(); private StringBuilder receivedDataBuffer1 = new StringBuilder(); private StringBuilder receivedDataBuffer2 = new StringBuilder(); private StringBuilder receivedDataBuffer3 = new StringBuilder(); private StringBuilder receivedDataBuffer4 = new StringBuilder(); string sPort0_ReceiveStr = ""; string sPort1_ReceiveStr = ""; string sPort2_ReceiveStr = ""; string sPort3_ReceiveStr = ""; string sPort4_ReceiveStr = ""; // 获取执行程序的根目录路径 public static string rootPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory); public Form1() { InitializeComponent(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { //新建任务流程csv文件 string TaskCSVname = rootPath + "\\" + "串口数据列表.csv"; if (!File.Exists(TaskCSVname)) { try { using (FileStream fs = File.Create(TaskCSVname)) { } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show($"创建用户程序 任务流程csv文件时发生错误: {ex.Message}"); } } if (File.Exists(TaskCSVname)) { SaveDataGridViewToCsv(TaskCSVname, dataGridView); } } private void Form1_Load(object sender, EventArgs e) { DataGridViewComboBoxColumn comboBoxColumn_COM = dataGridView.Columns[2] as DataGridViewComboBoxColumn; DataGridViewComboBoxColumn comboBoxColumn_Baudrate = dataGridView.Columns[3] as DataGridViewComboBoxColumn; DataGridViewComboBoxColumn comboBoxColumn_Databits = dataGridView.Columns[4] as DataGridViewComboBoxColumn; DataGridViewComboBoxColumn comboBoxColumn_Stopbit = dataGridView.Columns[5] as DataGridViewComboBoxColumn; DataGridViewComboBoxColumn comboBoxColumn_Checkbit = dataGridView.Columns[6] as DataGridViewComboBoxColumn; DataGridViewComboBoxColumn comboBoxColumn_End = dataGridView.Columns[7] as DataGridViewComboBoxColumn; DataGridViewComboBoxColumn comboBoxColumn_Agreement = dataGridView.Columns[8] as DataGridViewComboBoxColumn; string[] portNames = SerialPort.GetPortNames(); // 获取所有可用串口的名字[^3] string[] Baudrate_strs = { "9600", "19200", "38400", "56000", "115200" }; string[] Databits_strs = { "7", "8" }; string[] Stopbit_strs = { "1","2" }; string[] Checkbit_strs = { "无校验","奇校验", "偶校验" }; string[] End_strs = { "无", "/r", "/n", "/r/n" }; string[] Agreement_strs = { "通用", "Modbus_RTU" }; foreach (string portName in portNames) { comboBoxColumn_COM.Items.Add(portName); } foreach (string Baudrate_str in Baudrate_strs) { comboBoxColumn_Baudrate.Items.Add(Baudrate_str); } foreach (string Databits_str in Databits_strs) { comboBoxColumn_Databits.Items.Add(Databits_str); } foreach (string Stopbit_str in Stopbit_strs) { comboBoxColumn_Stopbit.Items.Add(Stopbit_str); } foreach (string Checkbit_str in Checkbit_strs) { comboBoxColumn_Checkbit.Items.Add(Checkbit_str); } foreach (string End_str in End_strs) { comboBoxColumn_End.Items.Add(End_str); } foreach (string Agreement_str in Agreement_strs) { comboBoxColumn_Agreement.Items.Add(Agreement_str); } string UserProTaskCSVname = rootPath + "\\" + "串口数据列表.csv"; //读取用户程序 任务流程csv文件 if (File.Exists(UserProTaskCSVname)) { LoadCsvToFixedDataGridView(UserProTaskCSVname, dataGridView); } else { } } private void dataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e) { string open_state = ""; string close_state = ""; // 获取点击的行索引和列索引 int rowIndex = e.RowIndex; int columnIndex = e.ColumnIndex; // 判断是否为按钮列 if (dataGridView.Columns[columnIndex] is DataGridViewButtonColumn && rowIndex >= 0) { string dgvPortName_str = dataGridView.Rows[rowIndex].Cells[2].FormattedValue.ToString(); string dgvBaudrate_str= dataGridView.Rows[rowIndex].Cells[3].FormattedValue.ToString(); string dgvDatabits_str = dataGridView.Rows[rowIndex].Cells[4].FormattedValue.ToString(); string dgvStopbit_str = dataGridView.Rows[rowIndex].Cells[5].FormattedValue.ToString(); string dgvCheckbit_str = dataGridView.Rows[rowIndex].Cells[6].FormattedValue.ToString(); string dgvAgreement_str= dataGridView.Rows[rowIndex].Cells[8].FormattedValue.ToString(); //打开连接按钮 if (columnIndex == 10) { if (rowIndex == 0) { if (dgvAgreement_str == "通用") { sPort_0 = new SerialPort(); sPort_open(sPort_0, dgvPortName_str, dgvBaudrate_str, dgvDatabits_str, dgvStopbit_str, dgvCheckbit_str, rowIndex, out open_state); } else if (dgvAgreement_str == "Modbus_RTU") { try { modbusrtu0 = new ModbusClient(dgvPortName_str); modbusrtu0.UnitIdentifier = 1; modbusrtu0.Baudrate = int.Parse(dgvBaudrate_str); // 获取选择的波特率 modbusrtu0.StopBits = StopBits.One; modbusrtu0.ConnectionTimeout = 500; //校验位 if (dgvCheckbit_str == "无") { modbusrtu0.Parity = Parity.None; } else if (dgvCheckbit_str == "奇校验") { modbusrtu0.Parity = Parity.Odd; } else if (dgvCheckbit_str == "偶校验") { modbusrtu0.Parity = Parity.Even; } // 尝试连接 modbusrtu0.Connect(); if (modbusrtu0.Connected) { open_state = "OK"; } } catch { open_state = "NG"; } if (open_state == "OK") { modbusThread0 = new Thread(ContBackgWork_modbusrtu0); modbusThread0.IsBackground = true; modbusThread0.Start(); } } if (open_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = true; } } else if (rowIndex == 1) { if (dgvAgreement_str == "通用") { sPort_1 = new SerialPort(); sPort_open(sPort_1, dgvPortName_str, dgvBaudrate_str, dgvDatabits_str, dgvStopbit_str, dgvCheckbit_str, rowIndex, out open_state); } else if (dgvAgreement_str == "Modbus_RTU") { try { modbusrtu1 = new ModbusClient(dgvPortName_str); modbusrtu1.UnitIdentifier = 1; modbusrtu1.Baudrate = int.Parse(dgvBaudrate_str); // 获取选择的波特率 modbusrtu1.StopBits = StopBits.One; modbusrtu1.ConnectionTimeout = 500; //校验位 if (dgvCheckbit_str == "无") { modbusrtu1.Parity = Parity.None; } else if (dgvCheckbit_str == "奇校验") { modbusrtu1.Parity = Parity.Odd; } else if (dgvCheckbit_str == "偶校验") { modbusrtu1.Parity = Parity.Even; } // 尝试连接 modbusrtu1.Connect(); if (modbusrtu1.Connected) { open_state = "OK"; } } catch { open_state = "NG"; } if (open_state == "OK") { modbusThread1 = new Thread(ContBackgWork_modbusrtu1); modbusThread1.IsBackground = true; modbusThread1.Start(); } } if (open_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = true; } } else if (rowIndex == 2) { if (dgvAgreement_str == "通用") { sPort_2 = new SerialPort(); sPort_open(sPort_2, dgvPortName_str, dgvBaudrate_str, dgvDatabits_str, dgvStopbit_str, dgvCheckbit_str, rowIndex, out open_state); } else if (dgvAgreement_str == "Modbus_RTU") { try { modbusrtu2 = new ModbusClient(dgvPortName_str); modbusrtu2.UnitIdentifier = 1; modbusrtu2.Baudrate = int.Parse(dgvBaudrate_str); // 获取选择的波特率 modbusrtu2.StopBits = StopBits.One; modbusrtu2.ConnectionTimeout = 500; //校验位 if (dgvCheckbit_str == "无") { modbusrtu2.Parity = Parity.None; } else if (dgvCheckbit_str == "奇校验") { modbusrtu2.Parity = Parity.Odd; } else if (dgvCheckbit_str == "偶校验") { modbusrtu2.Parity = Parity.Even; } // 尝试连接 modbusrtu2.Connect(); if (modbusrtu2.Connected) { open_state = "OK"; } } catch { open_state = "NG"; } if (open_state == "OK") { modbusThread2 = new Thread(ContBackgWork_modbusrtu2); modbusThread2.IsBackground = true; modbusThread2.Start(); } } if (open_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = true; } } else if (rowIndex == 3) { if (dgvAgreement_str == "通用") { sPort_3 = new SerialPort(); sPort_open(sPort_3, dgvPortName_str, dgvBaudrate_str, dgvDatabits_str, dgvStopbit_str, dgvCheckbit_str, rowIndex, out open_state); } else if (dgvAgreement_str == "Modbus_RTU") { try { modbusrtu3 = new ModbusClient(dgvPortName_str); modbusrtu3.UnitIdentifier = 1; modbusrtu3.Baudrate = int.Parse(dgvBaudrate_str); // 获取选择的波特率 modbusrtu3.StopBits = StopBits.One; modbusrtu3.ConnectionTimeout = 500; //校验位 if (dgvCheckbit_str == "无") { modbusrtu3.Parity = Parity.None; } else if (dgvCheckbit_str == "奇校验") { modbusrtu3.Parity = Parity.Odd; } else if (dgvCheckbit_str == "偶校验") { modbusrtu3.Parity = Parity.Even; } // 尝试连接 modbusrtu3.Connect(); if (modbusrtu3.Connected) { open_state = "OK"; } } catch { open_state = "NG"; } if (open_state == "OK") { modbusThread3 = new Thread(ContBackgWork_modbusrtu3); modbusThread3.IsBackground = true; modbusThread3.Start(); } } if (open_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = true; } } else if (rowIndex == 4) { if (dgvAgreement_str == "通用") { sPort_4 = new SerialPort(); sPort_open(sPort_4, dgvPortName_str, dgvBaudrate_str, dgvDatabits_str, dgvStopbit_str, dgvCheckbit_str, rowIndex, out open_state); } else if (dgvAgreement_str == "Modbus_RTU") { try { modbusrtu4 = new ModbusClient(dgvPortName_str); modbusrtu4.UnitIdentifier = 1; modbusrtu4.Baudrate = int.Parse(dgvBaudrate_str); // 获取选择的波特率 modbusrtu4.StopBits = StopBits.One; modbusrtu4.ConnectionTimeout = 500; //校验位 if (dgvCheckbit_str == "无") { modbusrtu4.Parity = Parity.None; } else if (dgvCheckbit_str == "奇校验") { modbusrtu4.Parity = Parity.Odd; } else if (dgvCheckbit_str == "偶校验") { modbusrtu4.Parity = Parity.Even; } // 尝试连接 modbusrtu4.Connect(); if (modbusrtu4.Connected) { open_state = "OK"; } } catch { open_state = "NG"; } if (open_state == "OK") { modbusThread4 = new Thread(ContBackgWork_modbusrtu4); modbusThread4.IsBackground = true; modbusThread4.Start(); } } if (open_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = true; } } } //关闭连接按钮 else if (columnIndex == 11) { if (rowIndex == 0) { if (dgvAgreement_str == "通用") { sPort_close(sPort_0, out close_state); } else if(dgvAgreement_str == "Modbus_RTU") { modbusThread0.Abort(); modbusrtu0.Disconnect(); close_state= "OK"; } if (close_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = false; } } else if (rowIndex == 1) { if (dgvAgreement_str == "通用") { sPort_close(sPort_1, out close_state); } else if (dgvAgreement_str == "Modbus_RTU") { modbusThread1.Abort(); modbusrtu1.Disconnect(); close_state = "OK"; } if (close_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = false; } } else if (rowIndex == 2) { if (dgvAgreement_str == "通用") { sPort_close(sPort_2, out close_state); } else if (dgvAgreement_str == "Modbus_RTU") { modbusThread2.Abort(); modbusrtu2.Disconnect(); close_state = "OK"; } if (close_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = false; } } else if (rowIndex == 3) { if (dgvAgreement_str == "通用") { sPort_close(sPort_3, out close_state); } else if (dgvAgreement_str == "Modbus_RTU") { modbusThread3.Abort(); modbusrtu3.Disconnect(); close_state = "OK"; } if (close_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = false; } } else if (rowIndex == 4) { if (dgvAgreement_str == "通用") { sPort_close(sPort_4, out close_state); } else if (dgvAgreement_str == "Modbus_RTU") { modbusThread4.Abort(); modbusrtu4.Disconnect(); close_state = "OK"; } if (close_state == "OK") { dataGridView.Rows[rowIndex].Cells[9].Value = false; } } } } } private void sPort_open(SerialPort sPort, string PortName, string Baudrate, string Databits, string Stopbit, string Checkbit,int Row,out string Result) { Result = ""; if (sPort.IsOpen == false) { try { sPort.PortName = PortName; // 获取选择的串口端口 sPort.BaudRate = int.Parse(Baudrate); // 获取选择的波特率 sPort.DataBits = int.Parse(Databits); // 数据位 //停止位 if (Stopbit == "1") { sPort.StopBits = StopBits.One; } else if (Stopbit == "2") { sPort.StopBits = StopBits.Two; } //校验位 if (Checkbit == "无校验") { sPort.Parity = Parity.None; } else if (Checkbit == "奇校验") { sPort.Parity = Parity.Odd; } else if (Checkbit == "偶校验") { sPort.Parity = Parity.Even; } // 打开串口 sPort.Open(); if (sPort.IsOpen) { if (Row == 0) { sPort.DataReceived += sPort0_DataReceived; } else if (Row == 1) { sPort.DataReceived += sPort1_DataReceived; } else if (Row == 2) { sPort.DataReceived += sPort2_DataReceived; } else if (Row == 3) { sPort.DataReceived += sPort3_DataReceived; } else if (Row == 4) { sPort.DataReceived += sPort4_DataReceived; } Result = "OK"; } } catch { Result = "NG"; } } else { Result = "opened"; } } private void sPort_close(SerialPort sPort, out string Result) { if (sPort != null && sPort.IsOpen) { sPort.Close(); Result = "OK"; } else { Result = "closed"; } } private void button1_Click(object sender, EventArgs e) { if (comboBox1.SelectedIndex == 0) { sPort_send(sPort_0, textBox1.Text); } else if (comboBox1.SelectedIndex == 1) { sPort_send(sPort_1, textBox1.Text); } else if (comboBox1.SelectedIndex == 2) { sPort_send(sPort_2, textBox1.Text); } } private void sPort_send(SerialPort sPort,string sendData) { if (sPort != null && sPort.IsOpen) { try { // 转换为字节数组并通过串口发送 byte[] buffer = Encoding.UTF8.GetBytes(sendData); sPort.Write(buffer, 0, buffer.Length); } catch (Exception ex) { MessageBox.Show("COM发送数据失败!"); } } } private void sPort0_DataReceived(object sender, SerialDataReceivedEventArgs e) { string end_str=dataGridView.Rows[0].Cells[7].FormattedValue.ToString(); // 创建临时存储空间保存本次读取的结果 byte[] buffer = new byte[sPort_0.BytesToRead]; int bytesReadCount = sPort_0.Read(buffer, 0, buffer.Length); // 追加新获取的内容至全局累积变量中 string newDataString = Encoding.UTF8.GetString(buffer, 0, bytesReadCount); receivedDataBuffer0.Append(newDataString); if (end_str == "/r" || end_str == "/n" || end_str == "/r/n") { int endIndex = 0; if (end_str == "/r") { endIndex = receivedDataBuffer0.ToString().LastIndexOf("\r"); } else if (end_str == "/n") { endIndex = receivedDataBuffer0.ToString().LastIndexOf("\n"); } else if (end_str == "/r/n") { endIndex = receivedDataBuffer0.ToString().LastIndexOf("\r\n"); } if (endIndex > 0) { // 提取消息主体部分 string completeMessage = receivedDataBuffer0.ToString(0, endIndex).Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer0.Remove(0, receivedDataBuffer0.Length); // 输出处理后的结果 sPort0_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } else if (end_str == "" || end_str == "无") { Thread.Sleep(100); // 提取消息主体部分 string completeMessage = receivedDataBuffer0.ToString().Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer0.Remove(0, receivedDataBuffer0.Length); // 输出处理后的结果 sPort0_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } private void sPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { string end_str = dataGridView.Rows[1].Cells[7].FormattedValue.ToString(); // 创建临时存储空间保存本次读取的结果 byte[] buffer = new byte[sPort_1.BytesToRead]; int bytesReadCount = sPort_1.Read(buffer, 0, buffer.Length); // 追加新获取的内容至全局累积变量中 string newDataString = Encoding.UTF8.GetString(buffer, 0, bytesReadCount); receivedDataBuffer1.Append(newDataString); if (end_str == "/r" || end_str == "/n" || end_str == "/r/n") { int endIndex = 0; if (end_str == "/r") { endIndex = receivedDataBuffer1.ToString().LastIndexOf("\r"); } else if (end_str == "/n") { endIndex = receivedDataBuffer1.ToString().LastIndexOf("\n"); } else if (end_str == "/r/n") { endIndex = receivedDataBuffer1.ToString().LastIndexOf("\r\n"); } if (endIndex > 0) { // 提取消息主体部分 string completeMessage = receivedDataBuffer1.ToString(0, endIndex).Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer1.Remove(0, receivedDataBuffer1.Length); // 输出处理后的结果 sPort1_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } else if (end_str == "" || end_str == "无") { Thread.Sleep(100); // 提取消息主体部分 string completeMessage = receivedDataBuffer1.ToString().Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer1.Remove(0, receivedDataBuffer1.Length); // 输出处理后的结果 sPort1_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } private void sPort2_DataReceived(object sender, SerialDataReceivedEventArgs e) { string end_str = dataGridView.Rows[2].Cells[7].FormattedValue.ToString(); // 创建临时存储空间保存本次读取的结果 byte[] buffer = new byte[sPort_2.BytesToRead]; int bytesReadCount = sPort_2.Read(buffer, 0, buffer.Length); // 追加新获取的内容至全局累积变量中 string newDataString = Encoding.UTF8.GetString(buffer, 0, bytesReadCount); receivedDataBuffer2.Append(newDataString); if (end_str == "/r" || end_str == "/n" || end_str == "/r/n") { int endIndex = 0; if (end_str == "/r") { endIndex = receivedDataBuffer2.ToString().LastIndexOf("\r"); } else if (end_str == "/n") { endIndex = receivedDataBuffer2.ToString().LastIndexOf("\n"); } else if (end_str == "/r/n") { endIndex = receivedDataBuffer2.ToString().LastIndexOf("\r\n"); } if (endIndex > 0) { // 提取消息主体部分 string completeMessage = receivedDataBuffer2.ToString(0, endIndex).Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer2.Remove(0, receivedDataBuffer2.Length); // 输出处理后的结果 sPort2_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } else if (end_str == "" || end_str == "无") { Thread.Sleep(100); // 提取消息主体部分 string completeMessage = receivedDataBuffer2.ToString().Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer2.Remove(0, receivedDataBuffer2.Length); // 输出处理后的结果 sPort2_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } private void sPort3_DataReceived(object sender, SerialDataReceivedEventArgs e) { string end_str = dataGridView.Rows[3].Cells[7].FormattedValue.ToString(); // 创建临时存储空间保存本次读取的结果 byte[] buffer = new byte[sPort_3.BytesToRead]; int bytesReadCount = sPort_3.Read(buffer, 0, buffer.Length); // 追加新获取的内容至全局累积变量中 string newDataString = Encoding.UTF8.GetString(buffer, 0, bytesReadCount); receivedDataBuffer3.Append(newDataString); if (end_str == "/r" || end_str == "/n" || end_str == "/r/n") { int endIndex = 0; if (end_str == "/r") { endIndex = receivedDataBuffer3.ToString().LastIndexOf("\r"); } else if (end_str == "/n") { endIndex = receivedDataBuffer3.ToString().LastIndexOf("\n"); } else if (end_str == "/r/n") { endIndex = receivedDataBuffer3.ToString().LastIndexOf("\r\n"); } if (endIndex > 0) { // 提取消息主体部分 string completeMessage = receivedDataBuffer3.ToString(0, endIndex).Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer3.Remove(0, receivedDataBuffer3.Length); // 输出处理后的结果 sPort3_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } else if (end_str == "" || end_str == "无") { Thread.Sleep(100); // 提取消息主体部分 string completeMessage = receivedDataBuffer3.ToString().Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer3.Remove(0, receivedDataBuffer3.Length); // 输出处理后的结果 sPort3_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } private void sPort4_DataReceived(object sender, SerialDataReceivedEventArgs e) { string end_str = dataGridView.Rows[4].Cells[7].FormattedValue.ToString(); // 创建临时存储空间保存本次读取的结果 byte[] buffer = new byte[sPort_4.BytesToRead]; int bytesReadCount = sPort_4.Read(buffer, 0, buffer.Length); // 追加新获取的内容至全局累积变量中 string newDataString = Encoding.UTF8.GetString(buffer, 0, bytesReadCount); receivedDataBuffer4.Append(newDataString); if (end_str == "/r" || end_str == "/n" || end_str == "/r/n") { int endIndex = 0; if (end_str == "/r") { endIndex = receivedDataBuffer4.ToString().LastIndexOf("\r"); } else if (end_str == "/n") { endIndex = receivedDataBuffer4.ToString().LastIndexOf("\n"); } else if (end_str == "/r/n") { endIndex = receivedDataBuffer4.ToString().LastIndexOf("\r\n"); } if (endIndex > 0) { // 提取消息主体部分 string completeMessage = receivedDataBuffer4.ToString(0, endIndex).Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer4.Remove(0, receivedDataBuffer4.Length); // 输出处理后的结果 sPort4_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } else if (end_str == "" || end_str == "无") { Thread.Sleep(100); // 提取消息主体部分 string completeMessage = receivedDataBuffer4.ToString().Trim(); // 清理缓冲区保留剩余未解析的部分 receivedDataBuffer4.Remove(0, receivedDataBuffer4.Length); // 输出处理后的结果 sPort4_ReceiveStr = completeMessage; // 执行进一步业务逻辑... } } //************************************ DataGridView操作方法 ***************************************** #region DataGridView操作方法 private void SaveDataGridViewToCsv(string filePath, DataGridView dgv) { StringBuilder sb = new StringBuilder(); // 添加表头 for (int colIdx = 0; colIdx < dgv.Columns.Count; colIdx++) { sb.Append(dgv.Columns[colIdx].HeaderText); if (colIdx != dgv.Columns.Count - 1) sb.Append(","); } sb.AppendLine(); // 遍历所有行并将数据追加到字符串中 foreach (DataGridViewRow row in dgv.Rows) { for (int cellIdx = 0; cellIdx < dgv.Columns.Count; cellIdx++) { if (dgv.Columns[cellIdx] is DataGridViewComboBoxColumn comboBoxCol) { sb.Append(row.Cells[cellIdx].FormattedValue); // 获取 ComboBox 显示值 } else if (dgv.Columns[cellIdx] is DataGridViewCheckBoxColumn checkBoxCol) { sb.Append(row.Cells[cellIdx].EditedFormattedValue.ToString()); // 获取 CheckBox 勾选状态 } else { sb.Append(row.Cells[cellIdx].Value?.ToString() ?? ""); // 普通文本列 } if (cellIdx != dgv.Columns.Count - 1) sb.Append(","); } sb.AppendLine(); } // 写入文件 System.IO.File.WriteAllText(filePath, sb.ToString(), Encoding.UTF8); } private void LoadCsvToFixedDataGridView(string filePath, DataGridView dgv) { dgv.Rows.Clear(); try { List<string[]> rowsData = new List<string[]>(); using (StreamReader sr = new StreamReader(filePath)) { string line; int rowIndex = 0; while ((line = sr.ReadLine()) != null) { if (rowIndex == 0) { rowIndex++; continue; } // 跳过表头 string[] rowData = line.Split(','); rowsData.Add(rowData); } } foreach (var rowData in rowsData) { object[] valuesToAdd = new object[dgv.Columns.Count]; for (int i = 0; i < dgv.Columns.Count; i++) { if (dgv.Columns[i] is DataGridViewComboBoxColumn comboBoxCol) { valuesToAdd[i] = comboBoxCol.Items.Cast<object>() .FirstOrDefault(item => item.ToString().Equals(rowData[i], StringComparison.OrdinalIgnoreCase)); } else if (dgv.Columns[i] is DataGridViewCheckBoxColumn checkBoxCol) { valuesToAdd[i] = bool.TryParse(rowData[i], out bool isChecked) ? isChecked : false; } else { valuesToAdd[i] = rowData[i]; } } dgv.Rows.Add(valuesToAdd); } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(dgv.Name.ToString() + " Failed to load data from CSV file." + Environment.NewLine + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } // 判断是否有足够的行可删 if (dgv.Rows.Count > 1) { // 获取最后一个非新行的索引 int lastIndex = dgv.Rows.Count - 2; // 移除该行 dgv.Rows.RemoveAt(lastIndex); } } #endregion private void ContBackgWork_modbusrtu0() { while (true) { try { modbusRtuInt_0 = modbusrtu0.ReadHoldingRegisters(0, 10); } catch { } Thread.Sleep(10); } } private void ContBackgWork_modbusrtu1() { while (true) { try { modbusRtuInt_1 = modbusrtu1.ReadHoldingRegisters(0, 10); } catch { } Thread.Sleep(10); } } private void ContBackgWork_modbusrtu2() { while (true) { try { modbusRtuInt_2 = modbusrtu2.ReadHoldingRegisters(0, 10); } catch { } Thread.Sleep(10); } } private void ContBackgWork_modbusrtu3() { while (true) { try { modbusRtuInt_3 = modbusrtu3.ReadHoldingRegisters(0, 10); } catch { } Thread.Sleep(10); } } private void ContBackgWork_modbusrtu4() { while (true) { try { modbusRtuInt_4 = modbusrtu4.ReadHoldingRegisters(0, 10); } catch { } Thread.Sleep(10); } } private void timer1_Tick(object sender, EventArgs e) { label1.Text = sPort0_ReceiveStr; label2.Text = sPort1_ReceiveStr; label3.Text = sPort2_ReceiveStr; }

这段代码中能解决重复添加水印的问题吗?每次添加水印之前先清空水印 import com.engine.doc.util.WaterMarkUtil; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import weaver.file.util.FileDeleteUtil; import weaver.general.BaseBean; import weaver.general.GCONST; import weaver.general.Util; import weaver.hrm.User; public class ImageMarkTwoUtil { public ImageMarkTwoUtil() { } public static void createMark(String var0, String var1, String var2, Color var3, float var4, String var5, int var6, int var7, Color var8) { String var9 = var1.contains(".") ? var1.substring(var1.lastIndexOf(".")) : ".JPG"; createMarkForPic2(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9); } public static void createMarkForPic1(String var0, String var1, String var2, Color var3, float var4, String var5, int var6, int var7, Color var8) { String var9 = var1.contains(".") ? var1.substring(var1.lastIndexOf(".")) : ".JPG"; createMarkForPic2(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9); } public static void createMarkForPic2(String var0, String var1, String var2, Color var3, float var4, String var5, int var6, int var7, Color var8, String var9) { createMarkForPic2(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9, (Map)null); } public static void createMarkForPic2(String var0, String var1, String var2, Color var3, float var4, String var5, int var6, int var7, Color var8, String var9, Map<String, Object> var10) { // 强制覆盖参数以满足需求 var6 = 12; // 固定为12pt(Word 5号字) int repeatTimes = 3; // 固定绘制3次 int startX = 30; // 左上角X起始位置 int startY = 30; // 左上角Y起始位置 int stepY = 40; // 每次绘制的垂直间距 // 修复点:在方法开始处声明并初始化为null FileOutputStream var11 = null; try { // 原代码读取图片逻辑 BufferedImage var22 = ImageIO.read(new File(var0)); int var23 = var22.getWidth(null); int var24 = var22.getHeight(null); BufferedImage var25 = new BufferedImage(var23, var24, BufferedImage.TYPE_INT_RGB); Graphics2D var26 = var25.createGraphics(); var26.drawImage(var22, 0, 0, var23, var24, null); // 设置字体(强制12pt加粗) var26.setFont(new Font(var5, Font.BOLD, var6)); FontMetrics var34 = var26.getFontMetrics(); // 设置抗锯齿 var26.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 设置透明度(保留原参数var4) var26.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, var4)); // 修改后的绘制逻辑(3次绘制+白字黑边) for (int i = 0; i < repeatTimes; i++) { int currentY = startY + (i * stepY); // 绘制黑色描边 var26.setColor(Color.BLACK); var26.drawString(var2, startX-1, currentY-1); var26.drawString(var2, startX+1, currentY-1); var26.drawString(var2, startX-1, currentY+1); var26.drawString(var2, startX+1, currentY+1); // 绘制白色文字 var26.setColor(Color.WHITE); var26.drawString(var2, startX, currentY); } var26.dispose(); // 输出文件 var11 = new FileOutputStream(var1); // 在此处初始化 String var50 = "JPG"; if (var9.indexOf(".") != -1) { var50 = var9.substring(var9.lastIndexOf(".") + 1); } ImageIO.write(var25, var50, var11); } catch (Exception var47) { var47.printStackTrace(); } finally { try { if (null != var11) { var11.close(); } } catch (Exception var46) { var46.printStackTrace(); } } } public static File startMark(InputStream var0, String var1, String var2) { try { BaseBean var3 = new BaseBean(); String var4 = Util.null2String(var3.getPropValue("PdfWaterMarkSet", "htmlwaterFont")); try { var4 = new String(var4.getBytes("ISO-8859-1"), "UTF-8"); } catch (Exception var15) { var4 = "Microsoft YaHei"; } String var5 = Util.null2String(var3.getPropValue("PdfWaterMarkSet", "htmlwaterColor")); try { var5 = new String(var5.getBytes("ISO-8859-1"), "UTF-8"); } catch (Exception var14) { var5 = "222,222,222"; } int var6 = 222; int var7 = 222; int var8 = 222; if (!"".equals(var5) && var5.indexOf(",") > 0) { String[] var9 = var5.split(","); if (var9 != null && var9.length >= 3) { var6 = Util.getIntValue(var9[0]); var7 = Util.getIntValue(var9[1]); var8 = Util.getIntValue(var9[2]); } } String var17 = getTargetFilePath(var2); File var10 = new File(var17); inputstreamtofile(var0, var10); String var11 = getTargetFilePath(var2); createMark(var17, var11, var1, (Color)null, 1.0F, var4, 25, 0, new Color(var6, var7, var8)); File var12 = new File(var17); (new FileDeleteUtil()).deleteFile(var12); (new FileDeleteUtil()).deleteFile(var10); File var13 = new File(var11); if (var13.exists()) { var0.close(); return var13; } } catch (Exception var16) { var16.printStackTrace(); } return null; } public static File addSystemImgwmForPic(InputStream var0, String var1, String var2, User var3) { BufferedImage var4 = null; try { HashMap var5 = new HashMap(); var5.put("isconvert", "1"); var5.put("document", "document"); Map var6 = WaterMarkUtil.getWmSetting(var5, var3); Map var7 = (Map)var6.get("wmSetting"); String var8 = Util.null2String(var7.get("opacity")); String var9 = Util.null2String(var7.get("rotate")); String var10 = Util.null2String(var7.get("wmwidth")); String var11 = Util.null2String(var7.get("wmheight")); int var12 = Util.getIntValue(var8); int var13 = Util.getIntValue(var9); int var14 = Util.getIntValue(var10); int var15 = Util.getIntValue(var11); String var16 = getTargetFilePath(var2); File var17 = new File(var16); inputstreamtofile(var0, var17); String var18 = getTargetFilePath(var2); var4 = ImageIO.read(var17); int var19 = var4.getWidth((ImageObserver)null); int var20 = var4.getHeight((ImageObserver)null); BufferedImage var21 = new BufferedImage(var19, var20, 1); Graphics2D var22 = var21.createGraphics(); var22.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); var22.drawImage(var4.getScaledInstance(var19, var20, 4), 0, 0, (ImageObserver)null); ImageIcon var23 = new ImageIcon(var1); Image var24 = var23.getImage(); var22.rotate(Math.toRadians((double)(-var13)), (double)var21.getWidth() / 2.0D, (double)var21.getHeight() / 2.0D); float var25 = (float)var12 / 100.0F; var22.setComposite(AlphaComposite.getInstance(10, var25)); int var26 = var20 / var15; int var27 = var19 / var14; for(int var28 = 0; var28 < var26 + 1; ++var28) { for(int var29 = 0; var29 < var27 + 1; ++var29) { var22.drawImage(var24, var14 * (var29 + 1) - var14 / 2, var15 * (var28 + 1) - var15 / 2, (ImageObserver)null); } } var22.setComposite(AlphaComposite.getInstance(3)); var22.dispose(); File var32 = new File(var18); ImageIO.write(var21, "jpg", var32); File var33 = new File(var16); (new FileDeleteUtil()).deleteFile(var33); (new FileDeleteUtil()).deleteFile(var17); File var30 = new File(var18); if (var30.exists()) { var0.close(); return var30; } } catch (IOException var31) { var31.printStackTrace(); } return null; } public static File addSystemWaterForPic(InputStream var0, String var1, String var2, User var3) { HashMap var4 = new HashMap(); var4.put("isconvert", "1"); var4.put("document", "document"); Map var5 = WaterMarkUtil.getWmSetting(var4, var3); Map var6 = (Map)var5.get("wmSetting"); String var7 = Util.null2String(var5.get("familyname")); String var8 = Util.null2String(var6.get("fontsize")); String var9 = Util.null2String(var6.get("color")); int var10 = Util.getIntValue(var8); try { new BaseBean(); String var12 = var7; try { new String(var12.getBytes("ISO-8859-1"), "UTF-8"); } catch (Exception var23) { var12 = "Microsoft YaHei"; } String var13 = WaterMarkUtil.stringtoRGB(var9); try { var13 = new String(var13.getBytes("ISO-8859-1"), "UTF-8"); } catch (Exception var22) { var13 = "222,222,222"; } int var14 = 128; int var15 = 128; int var16 = 128; if (!var13.isEmpty() && var13.indexOf(",") > 0) { String[] var17 = var13.split(","); if (var17 != null && var17.length >= 3) { var14 = Util.getIntValue(var17[0]); var15 = Util.getIntValue(var17[1]); var16 = Util.getIntValue(var17[2]); } } String var25 = getTargetFilePath(var2); File var18 = new File(var25); inputstreamtofile(var0, var18); String var19 = getTargetFilePath(var2); createMarkForPic2(var25, var19, var1, (Color)null, 1.0F, var7, var10, 10, new Color(var14, var15, var16), var2, var6); File var20 = new File(var25); (new FileDeleteUtil()).deleteFile(var20); (new FileDeleteUtil()).deleteFile(var18); File var21 = new File(var19); if (var21.exists()) { var0.close(); return var21; } } catch (Exception var24) { var24.printStackTrace(); } return null; } public static File startMarkForPic(InputStream var0, String var1, String var2) { try { BaseBean var3 = new BaseBean(); String var4 = Util.null2String(var3.getPropValue("PdfWaterMarkSet", "htmlwaterFont")); try { var4 = new String(var4.getBytes("ISO-8859-1"), "UTF-8"); } catch (Exception var15) { var4 = "Microsoft YaHei"; } String var5 = Util.null2String(var3.getPropValue("PdfWaterMarkSet", "htmlwaterColor")); try { var5 = new String(var5.getBytes("ISO-8859-1"), "UTF-8"); } catch (Exception var14) { var5 = "222,222,222"; } int var6 = 222; int var7 = 222; int var8 = 222; if (!"".equals(var5) && var5.indexOf(",") > 0) { String[] var9 = var5.split(","); if (var9 != null && var9.length >= 3) { var6 = Util.getIntValue(var9[0]); var7 = Util.getIntValue(var9[1]); var8 = Util.getIntValue(var9[2]); } } String var17 = getTargetFilePath(var2); File var10 = new File(var17); inputstreamtofile(var0, var10); String var11 = getTargetFilePath(var2); createMarkForPic2(var17, var11, var1, (Color)null, 1.0F, var4, 15, 10, new Color(var6, var7, var8), var2); File var12 = new File(var17); (new FileDeleteUtil()).deleteFile(var12); (new FileDeleteUtil()).deleteFile(var10); File var13 = new File(var11); if (var13.exists()) { var0.close(); return var13; } } catch (Exception var16) { var16.printStackTrace(); } return null; } private static String getTargetFilePath(String var0) { String var1 = GCONST.getRootPath() + "filesystem" + File.separatorChar + "docWaterMarkTemp"; File var2 = new File(var1); if (!var2.exists() && !var2.isDirectory()) { var2.mkdirs(); } UUID var3 = UUID.randomUUID(); var1 = var1 + File.separatorChar + var3.toString() + var0; return var1; } private static void inputstreamtofile(InputStream var0, File var1) { try { FileOutputStream var2 = new FileOutputStream(var1); boolean var3 = false; byte[] var4 = new byte[8192]; int var6; while((var6 = var0.read(var4, 0, 8192)) != -1) { var2.write(var4, 0, var6); } var2.close(); var0.close(); } catch (Exception var5) { var5.printStackTrace(); } } public static void drawString(Graphics2D var0, String var1, float var2, float var3, int var4, float var5, float var6, boolean var7, boolean var8) { if (var1 != null && var1.length() != 0) { if (var7) { var1 = var1.replaceAll("\\n+", "\n").trim(); } if (var8) { var1 = "  " + var1.replaceAll("\\n", "\n  "); } drawString(var0, var1, var2, var3, var4, var5, var6); } } public static void drawString(Graphics2D var0, String var1, float var2, float var3, int var4, float var5, float var6) { if (var1 != null && var1.length() != 0) { FontMetrics var7 = var0.getFontMetrics(); StringBuilder var8 = new StringBuilder(); for(int var9 = 0; var9 < var1.length(); ++var9) { char var10 = var1.charAt(var9); var8.append(var10); int var11 = var7.stringWidth(var8.toString()); if (var10 == '\n' || (float)var11 > var3) { if (var10 == '\n') { ++var9; } if (var4 > 1) { var0.drawString(var1.substring(0, var9), var5, var6); drawString(var0, var1.substring(var9), var2, var3, var4 - 1, var5, var6 + var2); } else { var0.drawString(var1.substring(0, var9 - 1) + "…", var5, var6); } return; } } var0.drawString(var1, var5, var6); } } public static ByteArrayOutputStream getOutputStream(InputStream var0) throws IOException { ByteArrayOutputStream var1 = new ByteArrayOutputStream(); try { byte[] var2 = new byte[1024]; int var3; while((var3 = var0.read(var2)) > -1) { var1.write(var2, 0, var3); } var1.flush(); } catch (Exception var4) { } return var1; } }

docx
pdf
docx

最新推荐

recommend-type

spnavcfg-0.3.1-1.el8.tar.gz

# 适用操作系统:Centos8 #Step1、解压 tar -zxvf xxx.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm
recommend-type

一个涵盖患者、疾病与药物关系的权威医疗 RDF 数据集

资源下载链接为: https://pan.quark.cn/s/7d4480e88650 一个涵盖患者、疾病与药物关系的权威医疗 RDF 数据集(最新、最全版本!打开链接下载即可用!)
recommend-type

【汽车电子电气】整车线束设计优化:从3D建模到降本增效的全流程解析及挑战应对了汽车电子电气

内容概要:本文详细阐述了汽车线束设计在整车电气系统中的重要性和设计流程。线束作为整车电子电气架构的物理实现,承担着连接ECU、传感器、执行器等模块的功能,贯穿车辆的动力、安全、智能驾驶等多个领域。文章从线束设计的核心作用、设计流程、核心挑战及降本措施四个方面展开。核心作用包括功能实现、安全保障、性能优化和成本控制;设计流程涵盖3D线束设计、电气原理设计和2D线束设计三个阶段;核心挑战涉及复杂系统集成、轻量化与成本平衡及试装验证;降本措施则通过国产化替代和设计优化来实现。 适合人群:从事汽车电子电气系统设计、开发及制造的工程师和技术人员,尤其是具备一定工作经验的研发人员。 使用场景及目标:①了解线束设计在整个汽车电气系统中的作用及其设计流程;②掌握线束设计的关键技术和挑战,如复杂系统集成、轻量化设计等;③学习如何通过国产化替代和设计优化降低成本并提高产品质量。 其他说明:本文不仅提供了详细的线束设计理论知识,还结合实际案例介绍了具体的实施路径和方法,旨在帮助读者全面理解和掌握线束设计的相关技术。阅读过程中,建议结合实际工程经验,重点关注设计流程中的关键技术点和降本措施的具体实施方案。
recommend-type

2007 年编写的基于 TcpClient 的 HTTP 请求库曾用于数据采集多年

资源下载链接为: https://pan.quark.cn/s/bd476d5a4ba6 2007 年编写的基于 TcpClient 的 HTTP 请求库曾用于数据采集多年(最新、最全版本!打开链接下载即可用!)
recommend-type

【计算机视觉】基于立体视觉的3D目标检测框架优化:联合2D边界框与实例深度估计的高效多类别检测系统设计(含详细代码及解释)

内容概要:这篇论文提出了一种基于立体视觉的3D目标检测框架,核心创新包括直接实例深度估计方法、自适应空间特征聚合模块。该框架仅用左图像生成联合2D边界框并预测3D框中心深度,通过减弱背景点影响并整合重要实例特征,提高了3D检测的精度和效率。相比现有方法,该框架在KITTI基准测试上表现出色,实现了更高的检测精度(68.7% AP)和更快的推理速度(8.5 FPS)。论文还详细介绍了框架的核心模块实现,如实例深度估计网络、自适应空间特征聚合模块以及完整的立体3D检测框架,并通过实验验证了各模块的有效性。 适合人群:从事计算机视觉、自动驾驶或机器人领域的研究人员和技术开发者,尤其是对3D目标检测、立体视觉感兴趣的从业者。 使用场景及目标:①提高3D目标检测精度和效率;②研究立体视觉在3D检测中的应用;③探索深度估计和特征聚合的新方法;④应用于自动驾驶、机器人导航等实际场景。 其他说明:论文不仅提供了理论分析,还给出了详细的代码实现,便于读者理解和复现。该框架在KITTI数据集上进行了充分验证,证明了其在多类别3D检测任务中的优越性能。此外,论文还讨论了现有方法的局限性,并提出了针对性的解决方案。
recommend-type

Ext4压缩与解压工具:从解包到重新打包全过程

标题和描述中提到的知识点详细说明如下: ### ext4文件系统 ext4(第四扩展文件系统)是Linux操作系统中的一个日志文件系统,它是在ext3基础上发展起来的。ext4提供了一系列改进,包括更大的文件系统和文件大小、更快的性能、更强的可靠性等。ext4文件系统广泛应用于Linux服务器和嵌入式设备中,特别是在Android操作系统中,它通常用于存储系统数据。 ### 解压工具 描述中提到了三个主要工具:make_ext4fs、simg2img和kusering.sh。这些工具主要用于Android设备的系统镜像文件的解压缩和重新打包操作。具体如下: 1. **make_ext4fs** 这是一个Android平台上的命令行工具,用于创建一个新的ext4文件系统镜像文件。这个工具通常用于打包修改过的文件系统或创建一个新的系统分区。其重要参数包括: - `-s`:创建一个sparse(稀疏)文件系统镜像。 - `-l`:设置文件系统的大小限制。 - `-a`:指定默认挂载点。 - `system.img`:输出的镜像文件名称。 - `tmp`:指定要打包的目录。 2. **simg2img** 该工具用于将Android专用的sparse格式镜像文件转换为普通的ext4文件系统镜像文件。这对于解包系统镜像文件和查看其中内容非常有用。其基本用法是: ```bash simg2img system.img system.img.ext4 ``` 这样就可以将一个sparse格式的system.img转换成ext4格式的system.img.ext4,后者能够被挂载到Linux系统中进行查看和修改。 3. **kusering.sh** 这个脚本可能是用于修改用户ID(UID)和组ID(GID)的脚本。在Android系统中,对系统分区进行操作时可能需要特殊的权限设置,而kusering.sh脚本正是用于此目的。但由于描述中没有具体的使用命令,无法给出具体用法。 ### 操作方法 描述中提供了一系列步骤来解压和修改system.img文件,并重新打包。下面详细介绍这些步骤: 1. **解压system.img为ext4格式**: 使用simg2img工具将sparse格式的system.img转换为ext4文件系统格式,命令如下: ```bash simg2img system.img system.img.ext4 ``` 这一步是必要的,因为原始的system.img通常是一个sparse格式,不易于直接修改。 2. **创建挂载目录**: 创建一个临时目录用于挂载ext4文件系统,命令如下: ```bash mkdir tmp ``` tmp目录将作为挂载点,用于将image文件挂载到Linux文件系统中。 3. **挂载ext4文件系统**: 将上一步得到的ext4文件系统挂载到之前创建的tmp目录,命令如下: ```bash sudo mount -t ext4 -o loop system.img.ext4 tmp ``` 使用`-t ext4`指定文件系统类型为ext4,`-o loop`创建一个循环设备,使得普通文件也能像块设备一样被访问。 4. **修改文件系统内容**: 进入tmp目录后,用户可以按照需求对文件系统内的内容进行修改。这一步通常需要root权限。 5. **重新打包文件系统**: 修改完成后,使用make_ext4fs工具将tmp目录重新打包为一个新的sparse格式的system.img文件,命令如下: ```bash sudo make_ext4fs -s -l 239M -a system system.img tmp ``` 这里`-s`表示创建sparse格式的文件系统,`-l 239M`指定文件系统的大小,`-a system`设置默认挂载点,`system.img`是打包后的输出文件名,`tmp`是作为文件系统源的目录。 ### 总结 以上步骤涵盖了如何使用simg2img、make_ext4fs工具进行Android设备的系统镜像的解压、挂载、修改和重新打包操作。需要注意的是,进行这些操作需要相应的Linux环境知识,以及对Android系统文件结构有一定的了解。由于这些操作涉及对系统分区的修改,建议在操作前备份原始的system.img文件,以防万一出现问题能够恢复。同时,由于这些操作可能会影响设备的正常使用,建议仅在允许的范围内进行。
recommend-type

【数据转换的基石】:技术分析,Excel到Oracle建表语句的自动化

# 摘要 本文主要探讨了数据转换项目中的关键步骤和自动化方法。首先,文章概述了数据源的分析与处理,重点在于理解Excel数据结构和进行数据清洗预处理。随后,文章介绍了利用VBA和Python语言实现Excel数据提取的自动化技术。接着,文章转向Oracle数据库建表语句的自动生成,涵盖了数据库基础、制定建表规则和模板,以及脚本编写的自动化过程。第五章整合了数据提取与建表流程,并通过案例实践展示了自动化数据转换项目的应用。
recommend-type

前端vue2 使用高德地图api

<think>好的,我现在需要解决用户的问题:如何在Vue2项目中集成和使用高德地图API。用户希望得到一个示例教程,并且根据提供的引用内容,我需要结合这些资料来构建答案。首先,我需要回顾用户提供的引用内容,看看有哪些关键点可以利用。 引用1、2、3、4、5都是关于Vue集成高德地图的,特别是引用4和5提到了Vue2和Vue3的具体集成步骤。用户问的是Vue2,所以需要重点参考引用4和5中的Vue2相关内容。不过引用5是Vue3的教程,可能部分步骤类似,但需要注意版本差异。 首先,步骤一般包括:注册高德开发者账号、获取API key、在Vue项目中引入高德地图的JS API、创建地图容器、
recommend-type

易语言源码:希冀程序保护专家深入解析

易语言是一种简单易学的编程语言,主要面向中文编程社区,其特色在于使用中文作为编程关键字。标题中提到的“希冀程序保护专家”可能是易语言编写的程序,旨在提供给易语言开发者使用的源码保护工具。 ### 易语言基础知识点 - **易语言的定义与特点:** 易语言是一种汉语编程语言,它的关键词和语法结构使用中文书写,极大降低了编程的学习难度,尤其适合编程初学者和没有英文基础的用户。 - **易语言的开发环境:** 易语言提供了一套集成开发环境(IDE),包括代码编辑器、调试器等,支持快速开发Windows应用程序。 - **易语言的应用范围:** 易语言广泛应用于桌面应用开发,如文本处理、游戏开发、系统管理工具等领域。 ### 程序保护的必要性 - **软件盗版与破解:** 在软件行业中,未经许可的复制和使用是一个普遍的问题。开发者需要采取措施保护其软件不被盗版和非法复制。 - **知识产权保护:** 程序保护是维护知识产权的一种方式,它帮助开发者保护其劳动成果不被他人侵权。 - **商业利益保护:** 软件如果被轻易破解,可能会导致开发者的经济损失。通过有效的程序保护,可以确保软件的合法销售和使用,维护开发者的商业利益。 ### 程序保护技术 - **代码混淆(Obfuscation):** 通过改变代码的结构和变量名来使程序难以阅读和分析,增加逆向工程的难度。 - **加壳(Packers):** 将可执行文件压缩,加密,使得程序在运行时首先执行一个解密或解压缩的过程,增加了程序被非法篡改的难度。 - **注册验证机制:** 通过软件注册码或激活机制,验证用户是否有权使用软件,限制非授权用户的使用。 - **许可证授权管理:** 程序运行时与远程服务器交互验证用户许可证,确保只有合法的用户可以使用软件。 ### 易语言的程序保护方案 - **代码混淆工具:** 易语言提供专门的混淆工具,开发者可以对源码进行混淆处理,提高代码安全性。 - **加密算法:** 易语言支持内置的加密解密函数库,开发者可以利用这些库函数实现加密算法,保护程序不被轻易破解。 - **模块化编程:** 易语言支持模块化开发,可以将核心功能封装在DLL模块中,通过主程序调用,增强保护效果。 - **第三方保护软件:** 如描述中的“希冀程序保护专家”,这样的工具往往集成了多种程序保护技术,如加壳、注册机生成、许可证管理等,提供一站式的服务。 ### 结论 易语言源码“希冀程序保护专家”面向的用户是使用易语言进行软件开发的程序员。这款工具能够帮助他们保护自己的易语言源码和编译后的可执行程序,防止源码被非法窃取,维护个人或公司的权益。通过实现各种程序保护技术,它能够提升软件的安全性,减少潜在的盗版风险,并且能够通过多种方式确保软件的授权使用,维护软件的市场价值。对于易语言开发者而言,这类保护工具是其软件能够获得市场成功的重要保障之一。
recommend-type

【数据迁移流程优化】:一步到位的Excel到Oracle建表语句自动化转换

# 摘要 本文旨在优化数据迁移流程,通过深入分析Excel与Oracle数据库的结构特点和数据处理技术,开发出一套自动化工具来实现高效的数据转换。文章首先概述了数据迁移流程,并对Excel数据结构和提取技术进行了详细分析。接着,介绍了Oracle数据库的基础知识,包括建表语句和数据库设计原则。在此基础上,文章详细描述了自动化转换工具的开发过程,包括