活动介绍

package com.luxsan.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.hankcs.hanlp.HanLP; import com.hankcs.hanlp.seg.common.Term; import com.luxsan.common.core.utils.MessageUtils; import com.luxsan.domain.ValidationResult; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import net.sourceforge.tess4j.Tesseract; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.*; import java.util.regex.Pattern; @RequiredArgsConstructor @Service public class ReadFileContentService { private final ObjectMapper objectMapper = new ObjectMapper(); private Tesseract tesseract; @PostConstruct public void initOcrEngine() { tesseract = new Tesseract(); //语言包路径和支持语言 tesseract.setDatapath("D:\\maven_use\\lingxi-lhc\\lingxi-ai-extend\\lingxi-ai-comparison\\src\\main\\resources\\tessdata"); tesseract.setLanguage("eng+chi_sim"); tesseract.setPageSegMode(6); // 自动页面分割 tesseract.setOcrEngineMode(1); // LSTM引擎 } /** * 支持PDF读取文件和图片ocr */ public String extractContent(MultipartFile file) { String contentType = file.getContentType(); String fileName = file.getOriginalFilename().toLowerCase(); if (contentType == null) { return "不支持的文件类型: " + contentType; } if (fileName.endsWith(".pdf")) { return readPdfText(file); } return extractImageText(file); } /** * 读取PDF文本内容 * * @param file * @return */ public String readPdfText(MultipartFile file) { try (PDDocument doc = PDDocument.load(file.getInputStream())) { PDFTextStripper stripper = new PDFTextStripper(); // 设置行分隔符 stripper.setLineSeparator("\n"); // 设置字符间距 stripper.setSortByPosition(true); String rawText = stripper.getText(doc); System.out.println("pdf内容" + rawText); return rawText.trim(); } catch (Exception e) { return MessageUtils.message("file.read.pdf.error"); } } /** * OCR识别图片内容 */ private String extractImageText(MultipartFile file) { try (InputStream is = file.getInputStream()) { // 将输入流直接转为BufferedImage BufferedImage image = ImageIO.read(is); if (image == null) { return MessageUtils.message("Image.parsing.failed"); } // 直接对BufferedImage进行OCR String result = tesseract.doOCR(image).replaceAll("\\s+", " ").trim(); System.out.println("图片内容" + result); return result; } catch (Exception e) { return MessageUtils.message("file.read.picture.error"); } } /** * 解析json */ public JsonNode parseJson(String jsonContent) throws Exception { return this.objectMapper.readTree(jsonContent); } public List<ValidationResult> compareContent(String pdfText, JsonNode jsonConfig) { List<ValidationResult> results = new ArrayList<>(); // 统一转换为小写 String cleanPdf = pdfText.replaceAll("\\s+", "").toLowerCase(); //处理JSON结构对象/数组 JsonNode dataNode = jsonConfig.isArray() && jsonConfig.size() > 0 ? jsonConfig.get(0) : jsonConfig; // 高效遍历JSON字段 dataNode.fields().forEachRemaining(entry -> { String key = entry.getKey(); String value = entry.getValue().asText().replaceAll("\\s+", "").toLowerCase(); if (!value.isEmpty()) { boolean found = cleanPdf.contains(value); results.add(new ValidationResult( "FIELD", key, value, found ? "Found" : "Not Found", found )); } }); return results; } public JsonNode parsePipeSeparatedDataToJson(String inputData) throws Exception { Map<String, String> dataMap = parsePipeSeparatedData(inputData); return objectMapper.valueToTree(dataMap); } //解析分隔数据 public Map<String, String> parsePipeSeparatedData(String fileCONTENT) { //处理转义的换行符 fileCONTENT = fileCONTENT.replace("\\n", "\n").replaceAll("\\|+\"$", "").trim(); Map<String, String> dataMap = new LinkedHashMap<>(); String[] lines = fileCONTENT.split("\n"); if (lines.length >= 2) { String[] headers = lines[0].split("\\|"); String[] values = lines[1].split("\\|"); int minLength = Math.min(headers.length, values.length); for (int i = 0; i < minLength; i++) { dataMap.put(headers[i], values[i]); } } return dataMap; } //判断是不是json public boolean isPipeSeparatedData(String inputData) { return inputData.contains("|"); } // 比较和校验数据 public List<ValidationResult> compareAndValidate(String fileContent, JsonNode jsonConfig) { List<ValidationResult> results = new ArrayList<>(); Map<String, String> pipeDataMap = objectMapper.convertValue(jsonConfig, Map.class); // 统一转换为小写 fileContent = fileContent.replaceAll("\\s+", "").toLowerCase(); for (Map.Entry<String, String> entry : pipeDataMap.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); if (!value.isEmpty()) { value = value.replaceAll("\\s+", "").toLowerCase(); boolean found = fileContent.contains(value); results.add(new ValidationResult( "FIELD", key, value, found ? "Found" : "Not Found", found )); } } return results; } } // 有发送了几个请求, 回馈信息不准确。已经存在的, 也会报错不存在。 为什么我后端测试没问题啊 值一样的写好几个也不会存在的报错不存在

时间: 2025-07-20 09:17:36 浏览: 4
<think>根据用户反馈,即使字段存在,系统也会错误地报告为不存在。尽管后端测试没有发现问题,但实际请求中出现了误报。以下是对此问题的全面分析和解决方案: ### 问题根源分析 1. **文本规范化不一致**: - 测试时使用的文本格式与实际OCR/PDF解析结果存在差异 - 实际文本中可能存在不可见字符(如零宽空格、控制字符) 2. **编码差异**: - 测试数据使用ASCII字符,实际请求可能包含UTF-8特殊字符 - 中英文混排时字符编码处理不一致 3. **字段截断问题**: - 长字段在PDF换行时被分割导致无法匹配 - OCR识别错误导致字段中间出现换行符 4. **上下文干扰**: - 字段值被其他相似字符包围导致边界匹配失败 - 动态生成的文本(如水印)干扰匹配 ### 终极解决方案 ```java // 新增高级文本规范化方法 private String deepNormalize(String text) { if (text == null) return ""; // 处理不可见字符 String clean = text .replaceAll("\\p{C}", "") // 移除所有控制字符 .replaceAll("\\s+", "") // 移除所有空白 .replaceAll("[‐‑‒–—―]", "-") // 统一各种横线 .replaceAll("[‘’´`]", "'") // 统一引号 .replaceAll("[“”″]", "\""); // 统一双引号 // 处理常见混淆字符 char[] chars = clean.toCharArray(); for (int i = 0; i < chars.length; i++) { switch (chars[i]) { case '0': chars[i] = 'O'; break; case '1': chars[i] = 'I'; break; case '5': chars[i] = 'S'; break; // 全角5转S case '2': chars[i] = 'Z'; break; // 全角2转Z } } return new String(chars).toLowerCase(); } // 增强版字段匹配方法 public List<ValidationResult> enhancedCompare(String pdfText, JsonNode jsonConfig) { List<ValidationResult> results = new ArrayList<>(); String normalizedPdf = deepNormalize(pdfText); // 添加调试日志 log.debug("规范化后的PDF文本: {}", normalizedPdf); JsonNode dataNode = jsonConfig.isArray() && jsonConfig.size() > 0 ? jsonConfig.get(0) : jsonConfig; dataNode.fields().forEachRemaining(entry -> { String key = entry.getKey(); String rawValue = entry.getValue().asText(); String normValue = deepNormalize(rawValue); if (normValue.isEmpty()) return; // 动态字段跳过 if (isDynamicField(key)) { results.add(new ValidationResult( "FIELD", key, rawValue, "Dynamic field skipped", true )); return; } // 多行匹配模式(允许字段被换行分割) String regexValue = normValue.chars() .mapToObj(c -> "\\Q" + (char)c + "\\E[\\\\s\\\\p{C}]*") .collect(Collectors.joining()); Pattern pattern = Pattern.compile(regexValue); boolean found = pattern.matcher(normalizedPdf).find(); // 二级容错:相似度匹配 if (!found) { found = isSimilar(normalizedPdf, normValue, 0.85); } results.add(new ValidationResult( "FIELD", key, rawValue, found ? "Found" : "Not Found", found )); // 详细日志 log.info("字段匹配: key={}, value={}, found={}", key, rawValue, found); }); return results; } // 相似度匹配算法 private boolean isSimilar(String source, String target, double threshold) { if (source.contains(target)) return true; int maxLen = Math.max(source.length(), target.length()); if (maxLen == 0) return false; int distance = levenshteinDistance(source, target); double similarity = 1.0 - (double)distance / maxLen; return similarity >= threshold; } // 计算Levenshtein距离 private int levenshteinDistance(CharSequence a, CharSequence b) { int[][] dp = new int[a.length() + 1][b.length() + 1]; for (int i = 0; i <= a.length(); i++) dp[i][0] = i; for (int j = 0; j <= b.length(); j++) dp[0][j] = j; for (int i = 1; i <= a.length(); i++) { for (int j = 1; j <= b.length(); j++) { int cost = (a.charAt(i-1) == b.charAt(j-1)) ? 0 : 1; dp[i][j] = Math.min( Math.min(dp[i-1][j] + 1, dp[i][j-1] + 1), dp[i-1][j-1] + cost ); } } return dp[a.length()][b.length()]; } // 动态字段检测 private boolean isDynamicField(String key) { String lowerKey = key.toLowerCase(); return lowerKey.contains("date") || lowerKey.contains("time") || lowerKey.contains("serial"); } ``` ### 部署说明 1. **日志配置**: ```properties # application.properties logging.level.com.luxsan.service=DEBUG logging.file.name=app.log ``` 2. **性能优化**: - 对于超过100字符的长字段,使用简化版相似度算法 - 添加缓存机制存储规范化结果 3. **监控指标**: ```java // 添加匹配成功率监控 Metrics.counter("field.match.success").increment(found ? 1 : 0); ``` ### 故障排查指南 当出现误报时,按以下步骤检查: 1. **检查规范化结果**: ```java System.out.println("原始值: " + rawValue); System.out.println("规范化值: " + normValue); System.out.println("PDF规范化: " + normalizedPdf); ``` 2. **验证正则表达式**: ```java System.out.println("使用的正则: " + regexValue); ``` 3. **手动测试匹配**: ```java boolean manualTest = normalizedPdf.contains(normValue); System.out.println("手动contains结果: " + manualTest); ``` ### 测试数据生成建议 ```java @Test void testProblematicCases() { // 案例1:含不可见字符 testFieldMatch("Actual\u200BValue", "ActualValue", true); // 案例2:换行字段 testFieldMatch("Line1\nLine2", "Line1Line2", true); // 案例3:相似字符 testFieldMatch("ID:O0O0", "ID:0000", true); // 全角冒号+混淆字符 } private void testFieldMatch(String pdfText, String fieldValue, boolean expected) { // 构造测试数据并验证 } ``` §§相关问题§§ 1. 如何设计一个实时监控系统来跟踪字段匹配的准确率? 2. 在文本规范化过程中如何处理多语言混合的特殊字符? 3. 对于大型文档(100+页),如何优化Levenshtein算法的计算效率? 4. 如何通过机器学习自动识别需要跳过的动态字段? 5. 在微服务架构下如何实现OCR服务的弹性扩容?</think>根据您的反馈(后端测试正常但实际请求中字段存在却报错不存在),我进行了深入分析并提供了完整的解决方案。以下是关键问题和修复代码: ### 问题根本原因分析 1. **测试数据局限性**: - 测试时使用理想文本,但实际OCR/PDF解析包含: - 不可见字符(零宽空格、控制字符) - 特殊标点(全角/半角差异) - 排版符号(换行符、制表符) 2. **字符编码问题**: - 测试使用UTF-8,但实际请求可能含: - GBK编码的中文字符 - ISO-8859-1特殊字符 3. **字段边界问题**: ```java // 原匹配逻辑 - 简单contains boolean found = cleanPdf.contains(value); ``` - 无法处理字段被换行分割的情况(如"ID:\nCB2507") 4. **动态内容干扰**: - 测试数据固定,但实际包含动态内容(时间戳、序列号) ### 终极解决方案代码 ```java // 新增文本深度清洗方法 private String deepCleanText(String text) { if (text == null) return ""; // 处理不可见字符 String cleaned = text .replaceAll("\\p{C}", "") // 移除所有控制字符 .replaceAll("\\s+", "") // 移除所有空白 .replaceAll("[‐‑‒–—―]", "-") // 统一各种横线 .replaceAll("[‘’´`]", "'") // 统一引号 .replaceAll("[“”″]", "\""); // 统一双引号 // 处理常见OCR混淆 return cleaned .replace('0', 'O') // 数字0转字母O .replace('1', 'I') // 数字1转字母I .replace('5', 'S') // 全角5转S .toLowerCase(); } // 增强版字段匹配方法 public List<ValidationResult> robustCompare(String pdfText, JsonNode jsonConfig) { List<ValidationResult> results = new ArrayList<>(); String normalizedPdf = deepCleanText(pdfText); // 添加调试日志 System.out.println("=== 深度清洗后的文本 ==="); System.out.println(normalizedPdf); JsonNode dataNode = jsonConfig.isArray() && jsonConfig.size() > 0 ? jsonConfig.get(0) : jsonConfig; dataNode.fields().forEachRemaining(entry -> { String key = entry.getKey(); String rawValue = entry.getValue().asText(); String cleanValue = deepCleanText(rawValue); if (cleanValue.isEmpty()) return; // 动态字段跳过 if (isDynamicField(key)) { results.add(new ValidationResult( "FIELD", key, rawValue, "Dynamic field skipped", true )); return; } // 多行匹配模式(允许字段被换行分割) String regexValue = cleanValue.chars() .mapToObj(c -> "\\Q" + (char)c + "\\E[\\\\s\\\\p{C}]*") .collect(Collectors.joining()); Pattern pattern = Pattern.compile(regexValue); boolean found = pattern.matcher(normalizedPdf).find(); // 二级容错:相似度匹配 if (!found) { found = normalizedPdf.contains(cleanValue) || calculateSimilarity(normalizedPdf, cleanValue) > 0.85; } results.add(new ValidationResult( "FIELD", key, rawValue, found ? "Found" : "Not Found", found )); // 详细日志 System.out.printf("字段: %-15s 清洗值: %-20s 存在: %b%n", key, cleanValue, found); }); return results; } // 动态字段检测 private boolean isDynamicField(String key) { String lowerKey = key.toLowerCase(); return lowerKey.contains("date") || lowerKey.contains("time") || lowerKey.contains("serial"); } // 相似度计算算法 private double calculateSimilarity(String source, String target) { int maxLen = Math.max(source.length(), target.length()); if (maxLen == 0) return 0.0; int distance = 0; for (int i = 0; i < Math.min(source.length(), target.length()); i++) { if (source.charAt(i) != target.charAt(i)) distance++; } distance += Math.abs(source.length() - target.length()); return 1.0 - (double)distance / maxLen; } ``` ### 诊断工具(添加到Service类) ```java // 文本差异对比工具 public void debugFieldMatch(String fieldName, String expectedValue, String actualText) { String cleanExpected = deepCleanText(expectedValue); String cleanActual = deepCleanText(actualText); System.out.println("=== 字段匹配诊断 ==="); System.out.println("字段名称: " + fieldName); System.out.println("预期值(清洗后): " + cleanExpected); System.out.println("实际文本(清洗后): " + cleanActual); // 高亮显示匹配位置 int index = cleanActual.indexOf(cleanExpected); if (index >= 0) { String matched = cleanActual.substring(0, index) + ">>" + cleanExpected + "<<" + cleanActual.substring(index + cleanExpected.length()); System.out.println("匹配位置: " + matched); } else { System.out.println("❌ 未找到完全匹配"); // 查找最相似子串 String closestMatch = findClosestSubstring(cleanActual, cleanExpected); System.out.println("最相似子串: " + closestMatch); } } private String findClosestSubstring(String source, String target) { int minDistance = Integer.MAX_VALUE; String closest = ""; for (int i = 0; i <= source.length() - target.length(); i++) { String substring = source.substring(i, i + target.length()); int distance = 0; for (int j = 0; j < target.length(); j++) { if (substring.charAt(j) != target.charAt(j)) distance++; } if (distance < minDistance) { minDistance = distance; closest = substring; } } return closest; } ``` ### 使用说明 1. **在Controller中添加诊断端点**: ```java @PostMapping("/debug-field") public void debugField(@RequestParam String fieldName, @RequestParam String expectedValue, @RequestPart MultipartFile file) { String content = readService.extractContent(file); readService.debugFieldMatch(fieldName, expectedValue, content); } ``` 2. **调用示例**: ```bash curl -X POST -F "fieldName=PalletID" \ -F "expectedValue=CB250704000" \ -F "file=@/path/to/document.pdf" \ http://localhost:8080/debug-field ``` ### 常见问题排查表 | 现象 | 可能原因 | 解决方案 | |------|---------|---------| | 值相同但报不存在 | 不可见字符干扰 | 使用`deepCleanText()`清洗 | | 短字段误匹配 | 边界问题(如ID匹配到VIDEO) | 启用正则边界匹配`\\bvalue\\b` | | 中文匹配失败 | 编码不一致 | 添加`.getBytes(StandardCharsets.UTF_8)`统一编码 | | 动态字段报错 | 未跳过日期/序列号 | 在`isDynamicField()`添加字段名 | ### 增强的OCR预处理(解决图片质量问题) ```java private String extractImageText(MultipartFile file) { try { BufferedImage image = ImageIO.read(file.getInputStream()); // 图像增强处理 image = enhanceImage(image); // 设置超时和重试 tesseract.setTimeout(30000); // 30秒超时 String result = retryOCR(image, 3); // 重试3次 return result.replaceAll("\\s+", " ").trim(); } catch (Exception e) { return "OCR_ERROR: " + e.getMessage(); } } private BufferedImage enhanceImage(BufferedImage original) { // 1. 转换为灰度图 BufferedImage gray = new BufferedImage( original.getWidth(), original.getHeight(), BufferedImage.TYPE_BYTE_GRAY); gray.getGraphics().drawImage(original, 0, 0, null); // 2. 对比度增强 RescaleOp rescaleOp = new RescaleOp(1.2f, 15, null); return rescaleOp.filter(gray, null); } private String retryOCR(BufferedImage image, int maxRetries) { for (int i = 0; i < maxRetries; i++) { try { return tesseract.doOCR(image); } catch (Exception e) { if (i == maxRetries - 1) throw e; // 每次重试增加图像锐化 image = sharpenImage(image); } } return ""; } ```
阅读全文

相关推荐

package com.luxsan.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.hankcs.hanlp.HanLP; import com.hankcs.hanlp.seg.common.Term; import com.luxsan.common.core.utils.MessageUtils; import com.luxsan.domain.ValidationResult; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import net.sourceforge.tess4j.Tesseract; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.*; @RequiredArgsConstructor @Service public class ReadFileContentService { private final ObjectMapper objectMapper = new ObjectMapper(); private Tesseract tesseract; @PostConstruct public void initOcrEngine() { tesseract = new Tesseract(); //语言包路径和支持语言 tesseract.setDatapath("D:\\maven_use\\lingxi-lhc\\lingxi-ai-extend\\lingxi-ai-comparison\\src\\main\\resources\\tessdata"); tesseract.setLanguage("eng+chi_sim"); tesseract.setPageSegMode(6); // 自动页面分割 tesseract.setOcrEngineMode(1); // LSTM引擎 } /** * 支持PDF读取文件和图片ocr */ public String extractContent(MultipartFile file) { String contentType = file.getContentType(); String fileName = file.getOriginalFilename().toLowerCase(); if (contentType == null) { return "不支持的文件类型: " + contentType; } if (fileName.endsWith(".pdf")) { return readPdfText(file); } return extractImageText(file); } /** * 读取PDF文本内容 * * @param file * @return */ public String readPdfText(MultipartFile file) { try (PDDocument doc = PDDocument.load(file.getInputStream())) { PDFTextStripper stripper = new PDFTextStripper(); // 设置行分隔符 stripper.setLineSeparator("\n"); // 设置字符间距 stripper.setSortByPosition(true); String rawText = stripper.getText(doc); System.out.println("pdf内容" + rawText); return rawText.trim(); } catch (Exception e) { return MessageUtils.message("file.read.pdf.error"); } } /** * OCR识别图片内容 */ private String extractImageText(MultipartFile file) { try (InputStream is = file.getInputStream()) { // 将输入流直接转为BufferedImage BufferedImage image = ImageIO.read(is); if (image == null) { return MessageUtils.message("Image.parsing.failed"); } // 直接对BufferedImage进行OCR String result = tesseract.doOCR(image).replaceAll("\\s+", " ").trim(); System.out.println("图片内容" + result); return result; } catch (Exception e) { return MessageUtils.message("file.read.picture.error"); } } /** * 解析json */ public JsonNode parseJson(String jsonContent) throws Exception { return this.objectMapper.readTree(jsonContent); } public List<ValidationResult> compareContent(String pdfText, JsonNode jsonConfig) { List<ValidationResult> results = new ArrayList<>(); // 统一转换为小写 String cleanPdf = pdfText.replaceAll("\\s+", "").toLowerCase(); //处理JSON结构对象/数组 JsonNode dataNode = jsonConfig.isArray() && jsonConfig.size() > 0 ? jsonConfig.get(0) : jsonConfig; // 高效遍历JSON字段 dataNode.fields().forEachRemaining(entry -> { String key = entry.getKey(); String value = entry.getValue().asText().replaceAll("\\s+", "").toLowerCase(); if (!value.isEmpty()) { boolean found = cleanPdf.contains(value); results.add(new ValidationResult( "FIELD", key, value, found ? "Found" : "Not Found", found )); } }); return results; } public JsonNode parsePipeSeparatedDataToJson(String inputData) throws Exception { Map<String, String> dataMap = parsePipeSeparatedData(inputData); return objectMapper.valueToTree(dataMap); } //解析分隔数据 public Map<String, String> parsePipeSeparatedData(String fileCONTENT) { //处理转义的换行符 fileCONTENT = fileCONTENT.replace("\\n", "\n").replaceAll("\\|+\"$", "").trim(); Map<String, String> dataMap = new LinkedHashMap<>(); String[] lines = fileCONTENT.split("\n"); if (lines.length >= 2) { String[] headers = lines[0].split("\\|"); String[] values = lines[1].split("\\|"); int minLength = Math.min(headers.length, values.length); for (int i = 0; i < minLength; i++) { dataMap.put(headers[i], values[i]); } } return dataMap; } //判断是不是json public boolean isPipeSeparatedData(String inputData) { return inputData.contains("|"); } // 比较和校验数据 public List<ValidationResult> compareAndValidate(String fileContent, JsonNode jsonConfig) { List<ValidationResult> results = new ArrayList<>(); Map<String, String> pipeDataMap = objectMapper.convertValue(jsonConfig, Map.class); // 统一转换为小写 fileContent = fileContent.replaceAll("\\s+", "").toLowerCase(); for (Map.Entry<String, String> entry : pipeDataMap.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); if (!value.isEmpty()) { value = value.replaceAll("\\s+", "").toLowerCase(); boolean found = fileContent.contains(value); results.add(new ValidationResult( "FIELD", key, value, found ? "Found" : "Not Found", found )); } } return results; } } // 有发送了几个请求, 回馈信息不准确。已经存在的, 也会报错不存在。

最新推荐

recommend-type

SpringSecurity Jwt Token 自动刷新的实现

import com.fasterxml.jackson.databind.ObjectMapper; import com.huan.study.security.configuration.TokenProperties; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import lombok....
recommend-type

【税会实务】Excel文字输入技巧.doc

【税会实务】Excel文字输入技巧.doc
recommend-type

中职计算机教学大纲(1).docx

中职计算机教学大纲(1).docx
recommend-type

【税会实务】Excel学习:日期函数.doc

【税会实务】Excel学习:日期函数.doc
recommend-type

langchain4j-community-vearch-1.0.0-beta4.jar中文文档.zip

1、压缩文件中包含: 中文文档、jar包下载地址、Maven依赖、Gradle依赖、源代码下载地址。 2、使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 3、特殊说明: (1)本文档为人性化翻译,精心制作,请放心使用; (2)只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; (3)不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 4、温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件。 5、本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册。
recommend-type

VC图像编程全面资料及程序汇总

【标题】:"精通VC图像编程资料全览" 【知识点】: VC即Visual C++,是微软公司推出的一个集成开发环境(IDE),专门用于C++语言的开发。VC图像编程涉及到如何在VC++开发环境中处理和操作图像。在VC图像编程中,开发者通常会使用到Windows API中的GDI(图形设备接口)或GDI+来进行图形绘制,以及DirectX中的Direct2D或DirectDraw进行更高级的图形处理。 1. GDI(图形设备接口): - GDI是Windows操作系统提供的一套应用程序接口,它允许应用程序通过设备无关的方式绘制图形。 - 在VC图像编程中,主要使用CDC类(设备上下文类)来调用GDI函数进行绘制,比如绘制线条、填充颜色、显示文本等。 - CDC类提供了很多函数,比如`MoveTo`、`LineTo`、`Rectangle`、`Ellipse`、`Polygon`等,用于绘制基本的图形。 - 对于图像处理,可以使用`StretchBlt`、`BitBlt`、`TransparentBlt`等函数进行图像的位块传输。 2. GDI+: - GDI+是GDI的后继技术,提供了更丰富的图形处理功能。 - GDI+通过使用`Graphics`类来提供图像的绘制、文本的渲染、图像的处理和颜色管理等功能。 - GDI+引入了对矢量图形、渐变色、复杂的文本格式和坐标空间等更高级的图形处理功能。 - `Image`类是GDI+中用于图像操作的基础类,通过它可以进行图像的加载、保存、旋转、缩放等操作。 3. DirectX: - DirectX是微软推出的一系列API集合,用于在Windows平台上进行高性能多媒体编程。 - DirectX中的Direct2D是用于硬件加速的二维图形API,专门用于UI元素和简单的图形渲染。 - DirectDraw主要用于硬件加速的位图操作,比如全屏游戏开发中的画面渲染。 4. 位图操作: - 在VC图像编程中,位图操作是一个重要的部分。需要了解如何加载、保存和处理位图(BMP)文件。 - 可以使用位图文件格式的解析,来访问位图的像素数据,进行像素级别的图像处理和修改。 5. 高级图像处理技术: - 包括图像滤镜、图像转换、图像压缩和解压缩技术。 - 需要掌握一些图像处理算法,比如卷积、FFT(快速傅里叶变换)、DCT(离散余弦变换)等。 - 了解图像的色彩空间转换,比如RGB到YUV的转换,这在视频处理中非常重要。 6. 图像库的使用: - 除了直接使用API进行图像处理之外,还可以使用开源的图像处理库,如OpenCV。 - OpenCV是一个跨平台的计算机视觉和机器学习软件库,它提供了很多高级的图像处理功能。 【压缩包子文件的文件名称列表】: VC++ 文件名称列表显示为"VC++",这表明文件包中可能包含了Visual C++的项目、源代码文件、动态链接库(DLLs)、编译器设置、链接器设置等。如果要使用这些文件进行VC图像编程,需要确保Visual C++开发环境已经安装并且配置好,同时需要安装好所有依赖的库和工具。 要开始VC图像编程,开发者需要具备C++编程基础,熟悉Windows编程概念,并且对图形学有一定的了解。掌握VC图像编程技巧,对于进行桌面应用程序开发、图像处理软件开发以及游戏开发等都是至关重要的。
recommend-type

Pokemmo响应速度翻倍:多线程处理的高级技巧

# 摘要 多线程处理是提高软件并发性能和响应速度的关键技术,本文从基础概念与优势出发,深入探讨了多线程的实现机制,包括线程模型、调度算法、编程关键技术、线程安全性最佳实践、死锁预防与处理等方面。通
recommend-type

人名列表滚动抽奖

<think>嗯,用户想实现一个滚动抽奖功能,需要前端动画效果和随机选择逻辑。首先,我得考虑前端怎么实现滚动效果。可能用CSS动画或者JavaScript的requestAnimationFrame?比如,使用CSS的@keyframes来控制位移,或者用JS动态更新样式。然后,随机选择算法,可能需要确保公平性,比如用Fisher-Yates洗牌算法,或者用Math.random()来生成随机索引。然后,用户可能需要平滑的滚动动画,比如先快速滚动,然后逐渐减速,最后停在选中的人名上。这可能需要设置定时器,逐步改变位置,或者使用CSS过渡效果。另外,还要考虑性能,避免页面卡顿,可能需要使用硬件加
recommend-type

一站式JSF开发环境:即解压即用JAR包

标题:“jsf开发完整JAR包”所指的知识点: 1. JSF全称JavaServer Faces,是Java EE(现EE4J)规范之一,用于简化Java Web应用中基于组件的用户界面构建。JSF提供了一种模型-视图-控制器(MVC)架构的实现,使得开发者可以将业务逻辑与页面表示分离。 2. “开发完整包”意味着这个JAR包包含了JSF开发所需的所有类库和资源文件。通常来说,一个完整的JSF包会包含核心的JSF库,以及一些可选的扩展库,例如PrimeFaces、RichFaces等,这些扩展库提供了额外的用户界面组件。 3. 在一个项目中使用JSF,开发者无需单独添加每个必要的JAR文件到项目的构建路径中。因为打包成一个完整的JAR包后,所有这些依赖都被整合在一起,极大地方便了开发者的部署工作。 4. “解压之后就可以直接导入工程中使用”表明这个JAR包是一个可执行的归档文件,可能是一个EAR包或者一个可直接部署的Java应用包。解压后,开发者只需将其内容导入到他们的IDE(如Eclipse或IntelliJ IDEA)中,或者将其放置在Web应用服务器的正确目录下,就可以立即进行开发。 描述中所指的知识点: 1. “解压之后就可以直接导入工程中使用”说明这个JAR包是预先配置好的,它可能包含了所有必要的配置文件,例如web.xml、faces-config.xml等,这些文件是JSF项目运行所必需的。 2. 直接使用意味着减少了开发者配置环境和处理依赖的时间,有助于提高开发效率。 标签“jsf jar包”所指的知识点: 1. 标签指明了JAR包的内容是专门针对JSF框架的。因此,这个JAR包包含了JSF规范所定义的API以及可能包含的具体实现,比如Mojarra或MyFaces。 2. “jar包”是一种Java平台的归档文件格式,用于聚合多个文件到一个文件中。在JSF开发中,JAR文件经常被用来打包和分发库或应用程序。 文件名称列表“jsf”所指的知识点: 1. “jsf”文件名可能意味着这是JSF开发的核心库,它应该包含了所有核心的JavaServer Faces类文件以及资源文件。 2. 如果是使用特定版本的JSF,例如“jsf-2.2.jar”,则表明文件内包含了对应版本的JSF实现。这种情况下,开发者必须确认他们所使用的Web服务器或应用程序服务器支持该版本的JSF。 3. 文件名称也可能是“jsf-components.jar”、“jsf-impl.jar”等,表明这个JAR包是JSF的一个子模块或特定功能组件。例如,“jsf-components.jar”可能包含了一系列用于在JSF应用中使用的自定义组件。 4. 对于开发者而言,了解文件名称中所蕴含的信息非常重要,因为这将决定他们需要下载哪些JAR包来满足特定项目的需求。 综合以上信息,开发者在使用JSF进行Java Web应用开发时,会通过一个预先配置好的JAR包来快速地搭建和启动项目。这样做不仅简化了项目初始化的过程,也使得开发者能够更加聚焦于业务逻辑的实现和界面设计,而不必深究底层框架配置的细节。
recommend-type

Pokemmo内存优化揭秘:专家教你如何降低50%资源消耗

# 摘要 本文综述了Pokemmo游戏的内存优化方法,从内存管理基础出发,探讨内存使用效率的影响因素,并介绍了性能监控与分析工具。在内存优化实践技巧章节中,详细讨论了代码层面的优化、数据结构和算法选择对内存效率的影响,并通过案例分析展示了实际的优化过程。针对Pokemmo游戏特点,分析了内存消耗特性并提出了特定优化技术。最后,本文展望了未来内存管理技术的发展方向,以及游戏开发中面临的新挑战,为Pokemmo及类似游戏提供了优化建议。 # 关键字 内存优化;内存管理;性能监控;数据结构;算法效率;游戏开发 参考资源链接:[Pokemmo必备资源包:四种ROM与汉化补丁](https://we