java解析PDF、WORD获取其中的表格以及文本内容

近期因工作需要需要解析PDF,需要把PDF中的文本和表格分离,最终要实现的目标是PDF中的文本内容放一块,表格内容放一块,以list的形式存储。解析PDF的技术有很多,经过多次尝试发现使用AdobeAcrobat可以实现表格和文本分离。

注意事项:

1、下载AdobeAcrobat进行安装
       链接:https://pan.baidu.com/s/1Ki2H4gxDaKj5z8Dli3amCg 
       提取码:ckfx

2、使用时如果有报jacob的错把jacob-1.18-M1-x64.dll、jacob-1.18-M1-x86.dll这两个文件放到Java>jdk1.8.0_271>bin目录下

3、引入依赖:

     <dependency>
       <groupId>jacob</groupId>
       <artifactId>jacob</artifactId>
       <version>1.1.8</version>
     </dependency> 
     <dependency>
	   <groupId>org.jsoup</groupId>
	   <artifactId>jsoup</artifactId>
	   <version>1.17.2</version>
	 </dependency>

工具类如下(内附PDF的文件转换方法以及获取纯文本和纯表格的测试方法):

package com.ylx.test.util;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/**
 * 
 * 2024年4月18日下午3:53:36
 */
@Component
public class PdfToHtmlAdobe {
	
	public static void main(String[] args) throws Exception {
		/**
		 * 将PDF转成html
		 * */
        String filepath = "E:\\工作\\";
		String htmlpath = "E:\\gongzuo\\zjk\\html_file\\";
		String filename = "cehi";
		Integer fileType = 1;//1.pdf,2word
		String ext = ".pdf";
		filedata(filepath, filename,htmlpath,fileType,ext);

        /**
		 * 获取纯文本
		 * */
		String htmlFilePath = "E:\\gongzuo\\html_file\\ceshi.html";
		List<String> dlList = getDLList(htmlFilePath);
		for (int i = 0; i < dlList.size(); i++) {
			System.out.println("第"+i+"条:"+dlList.get(i));
		}
		/**
		 * 获取所有表格
		 * */
		List<String> bgList = getAllTable(htmlFilePath);
		for (int i = 0; i < bgList.size(); i++) {
			System.out.println("第"+i+"条:"+bgList .get(i));
		}
		
	}
	
	public static String getRemoveTableStr(String htmlFilePath) throws IOException {
		String content = new String(Files.readAllBytes(Paths.get(htmlFilePath)),"GBK");
		String specialStr = removeContentStyle(content);
		// 使用 Jsoup 解析 HTML 字符串
        Document doc = Jsoup.parse(specialStr);

        // 获取纯文本
        String plainText = doc.text();
//		System.out.println(plainText);
        return plainText;
	}
	
	/**
	 * 获取所有的Table
	 * @param htmlFilePath
	 * @return
	 * @throws IOException
	 * 2024年4月19日下午3:36:39
	 */
	public static List<String> getAllTable(String htmlFilePath) throws IOException {
		List<String> bgList = new ArrayList<>();
		// 加载 HTML 文件
        File input = new File(htmlFilePath);
        
        try {
            // 解析 HTML 文件
            Document doc = Jsoup.parse(input, null);
            
            // 选择所有的表格元素
            Elements tables = doc.select("table");
            
            // 遍历每个表格元素
            for (Element table : tables) {
            	// 获取当前表格中的所有行
                Elements rows = table.select("tr");
                
              //创建StringBuilder类的实例
                StringBuilder builder = new StringBuilder();
                // 遍历每行
                for (Element row : rows) {
                    // 输出行内容
//                    System.out.println("行内容:");
//                    System.out.println(row.text());
                  //将获取的text写入StringBuilder容器
                    builder.append(row.text());
                    builder.append("\r\n");
                }
//                System.out.println("-----------------------------------------------");
//                System.out.println(builder.toString());
//                System.out.println("-----------------------------------------------");
                bgList.add(builder.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		return bgList;
	}
	
	/**
	 * 获取以10个逗号为一个段落的list
	 * @param content
	 * @return
	 * 2024年4月19日下午2:04:17
	 * @throws IOException 
	 */
	public static List<String> getDLList(String htmlFilePath) throws IOException {
		/**
		 * 删除Table表格
		 * */
		String content = getRemoveTableStr(htmlFilePath);
//		System.out.println(content);
//        String[] jhArr = content.split("。");
//        List<String> dlList = new ArrayList<String>();//10个句号为一个段落
//        String jhStrTen=new String();
//        int lastDl=0;
//        for (int i = 0; i < jhArr.length; i++) {
//        	if (i % 10 == 0 && i>0) {
//        		dlList.add(jhStrTen);
//        		if (jhArr.length-i>10) {
//        			jhStrTen="";
//				}
//        		if (jhArr.length-i<=10 && lastDl==0) {
//					lastDl = 1;
//					jhStrTen = "";
//				}
//			}else{
//				jhStrTen = jhStrTen +jhArr[i]+"。";
//				if ((i+1) == jhArr.length) {
//					dlList.add(jhStrTen);
//				}
//			}
//		}
        
        List<String> dlList = new ArrayList<>();
        int index = 0;
        while (index < content.length()) {
            int endIndex = index + 1; // 初始化结束索引
            for (int i = 0; i < 10; i++) {
                endIndex = content.indexOf("。", endIndex + 1); // 查找句号
                if (endIndex == -1) {
                    break; // 如果没有找到句号,跳出循环
                }
            }
            if (endIndex == -1) {
                endIndex = content.length(); // 如果不满十个句号,结束索引为字符串长度
            }
            dlList.add(content.substring(index, endIndex)); // 将段落添加到列表中
            index = endIndex + 1; // 更新起始索引
        }
        
		return dlList;
	}
	
	
	/**
	 * @param filepath  存放PDF的文件目录
	 * @param filename  不带后缀名的PDF文件
	 * @throws Exception
	 * 2024年4月18日下午3:31:55
	 */
	public static void filedata(String fileDir, String filename,String htmlPath,Integer fileType,String ext) throws Exception{
		final ExecutorService exec = Executors.newFixedThreadPool(1);  
        
        Callable<String> call = new Callable<String>() {  
            public String call() throws Exception {  
                //开始执行耗时操作  
            	if (fileType==1) {
            		//文件路径不存在则进行创建
            		FileUtils.createPath(htmlPath);
            		if (!FileUtils.isFileExists(htmlPath + filename + ".docx")) {
            			PDFtoWord(fileDir + filename + ".PDF", htmlPath + filename + ".docx");
            		}
            		if (!FileUtils.isFileExists(htmlPath + filename + ".html")) {
            			wordToHtml(htmlPath + filename + ".docx", htmlPath + filename + ".html");
            		}
				}
            	if (fileType==2){
            		//文件路径不存在则进行创建
            		FileUtils.createPath(htmlPath);
            		if (!FileUtils.isFileExists(htmlPath + filename + ".html")) {
            			wordToHtml(fileDir + filename + ext, htmlPath + filename + ".html");
            		}
				}
                return "线程执行完成.";
            }  
        };  
        try {
        	Future<String> future = exec.submit(call);
            String obj = future.get(1000 * 600, TimeUnit.MILLISECONDS); //任务处理超时时间设为 1 秒  
            System.out.println("文件转换:" + obj);
		} catch (Exception e) {
			//关闭Acrobat
    		String command = "taskkill /f /im Acrobat.exe";  
    		Runtime.getRuntime().exec(command);
			throw e;
		} finally {
			// 关闭线程池  
	        exec.shutdown(); 
		}
	}
	
	public static boolean wordToHtml(String inPath, String toPath) {
		ComThread.InitSTA();//初始化com的线程
		// 启动word

		ActiveXComponent axc = new ActiveXComponent("Word.Application");

		boolean flag = false;

		try {

			// 设置word不可见

			axc.setProperty("Visible", new Variant(false));

			Dispatch docs = axc.getProperty("Documents").toDispatch();

			// 打开word文档

			Dispatch doc = Dispatch.invoke(

					docs,

					"Open",

					Dispatch.Method,

					new Object[] { inPath, new Variant(false), new Variant(true) },

					new int[1]).toDispatch();

			// 作为html格式保存到临时文件

			Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {

					toPath, new Variant(8) }, new int[1]);

			Variant f = new Variant(false);

			Dispatch.call(doc, "Close", f);
			
			axc.invoke("Quit", new Variant[] {});

			flag = true;

			return flag;

		} catch (Exception e) {

			e.printStackTrace();

			return flag;

		} finally {
			
			ComThread.Release();//关闭com的线程   真正kill进程
		}

	}

	public static boolean PDFtoWord(String source, String target) {
		ComThread.InitSTA();//初始化com的线程
		// pdfActiveX PDDoc对象 主要建立PDF对象
		ActiveXComponent app = null ;
		try {
			File inPath = new File(source);
			File outPath = new File(target);
			app = new ActiveXComponent("AcroExch.PDDoc");
			// PDF控制对象
			Dispatch pdfObject = app.getObject();
			long start = System.currentTimeMillis();
			// 打开PDF文件,建立PDF操作的开始
			Dispatch.call(pdfObject, "Open", new Variant(inPath.getAbsolutePath()));
			Variant jsObj = Dispatch.call(pdfObject, "GetJSObject");
			Dispatch.call(jsObj.getDispatch(), "SaveAs", outPath.getPath(), "com.adobe.acrobat.docx");
			app.invoke("Close");
			// 关闭PDF
			app.invoke("Close", new Variant[] {});
			long end = System.currentTimeMillis();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		} finally {
			ComThread.Release();//关闭com的线程   真正kill进程
		}
		
		return true;
	}
	
	public static String chineseDate(String chineseDate){
		String aa4 = chineseDate.substring(chineseDate.indexOf("年")-2, chineseDate.indexOf("年"));
		String aa1 = chineseDate.substring(chineseDate.indexOf("年"),chineseDate.indexOf("月")+1);
		String aa2 = chineseDate.substring(chineseDate.indexOf("月")+1,chineseDate.indexOf("日"));
		String aa3 = chineseDate.substring(chineseDate.indexOf("日"));
		aa1 = aa1.replaceAll("十二", "12");
		aa1 = aa1.replaceAll("十一", "11");
		aa1 = aa1.replaceAll("十", "10");
		aa1 = aa1.replaceAll("一", "1");
		aa1 = aa1.replaceAll("二", "2");
		aa1 = aa1.replaceAll("三", "3");
		aa1 = aa1.replaceAll("四", "4");
		aa1 = aa1.replaceAll("五", "5");
		aa1 = aa1.replaceAll("六", "6");
		aa1 = aa1.replaceAll("七", "7");
		aa1 = aa1.replaceAll("八", "8");
		aa1 = aa1.replaceAll("九", "9");
		aa1 = aa1.replaceAll("零", "0");
		aa1 = aa1.replaceAll("〇", "0");
		aa1 = aa1.replaceAll("○", "0");
		aa1 = aa1.replaceAll("O", "0");
		aa1 = aa1.replaceAll("", "0");
		aa4 = aa4.replaceAll("十二", "12");
		aa4 = aa4.replaceAll("十一", "11");
		aa4 = aa4.replaceAll("十", "10");
		aa4 = aa4.replaceAll("一", "1");
		aa4 = aa4.replaceAll("二", "2");
		aa4 = aa4.replaceAll("三", "3");
		aa4 = aa4.replaceAll("四", "4");
		aa4 = aa4.replaceAll("五", "5");
		aa4 = aa4.replaceAll("六", "6");
		aa4 = aa4.replaceAll("七", "7");
		aa4 = aa4.replaceAll("八", "8");
		aa4 = aa4.replaceAll("九", "9");
		aa4 = aa4.replaceAll("零", "0");
		aa4 = aa4.replaceAll("〇", "0");
		aa4 = aa4.replaceAll("○", "0");
		aa4 = aa4.replaceAll("O", "0");
		aa4 = aa4.replaceAll("", "0");
		return 20+aa4+aa1+chineseNumber(aa2)+aa3;
	}
	
	/**
     * 中文數字转阿拉伯数组【十万九千零六十  --> 109060】
     * @param chineseNumber
     * @return
     */
    private static String chineseNumber(String chineseNumber){
        int result = 0;
        int temp = 1;//存放一个单位的数字如:十万
        int count = 0;//判断是否有chArr
        char[] cnArr = new char[]{'一','二','三','四','五','六','七','八','九'};
        char[] chArr = new char[]{'十','百','千','万','亿'};
        for (int i = 0; i < chineseNumber.length(); i++) {
            boolean b = true;//判断是否是chArr
            char c = chineseNumber.charAt(i);
            for (int j = 0; j < cnArr.length; j++) {//非单位,即数字
                if (c == cnArr[j]) {
                    if(0 != count){//添加下一个单位之前,先把上一个单位值添加到结果中
                        result += temp;
                        temp = 1;
                        count = 0;
                    }
                    // 下标+1,就是对应的值
                    temp = j + 1;
                    b = false;
                    break;
                }
            }
            if(b){//单位{'十','百','千','万','亿'}
                for (int j = 0; j < chArr.length; j++) {
                    if (c == chArr[j]) {
                        switch (j) {
                        case 0:
                            temp *= 10;
                            break;
                        case 1:
                            temp *= 100;
                            break;
                        case 2:
                            temp *= 1000;
                            break;
                        case 3:
                            temp *= 10000;
                            break;
                        case 4:
                            temp *= 100000000;
                            break;
                        default:
                            break;
                        }
                        count++;
                    }
                }
            }
            if (i == chineseNumber.length() - 1) {//遍历到最后一个字符
                result += temp;
            }
        }
        return String.valueOf(result);
    }
    
    
    /**
	 *  读取本地html文件里的html代码
	 * @return
	 */
	public static String toHtmlString(File file) {
	    // 获取HTML文件流
	    StringBuffer htmlSb = new StringBuffer();
	    try {
	        BufferedReader br = new BufferedReader(new InputStreamReader(
	                new FileInputStream(file), "GBK"));
	        while (br.ready()) {
	            htmlSb.append(br.readLine());
	        }
	        br.close();
	        // 删除临时文件
	        //file.delete();
	    } catch (FileNotFoundException e) {
	        e.printStackTrace();
	    } catch (IOException e) {
	        e.printStackTrace();
	    }
	    // HTML文件字符串
	    String htmlStr = htmlSb.toString();
	    // 返回经过清洁的html文本
	    return htmlStr;
	}
	
	/**
     * 符合以特定字符串开头 ,以特定字符串结尾的所有结果
     */
    public static String getSpecialStr(String line, String pattern) {
            // 创建 Pattern 对象
            Pattern r = Pattern.compile(pattern);
            // 创建 matcher 对象
            Matcher m = r.matcher(line);
            String str = "";
            if (m.find()) {
                    str = m.group(2);
            }
            if (StringUtils.isEmpty(str)) {
                    return str;
            } else {
                    return str.substring(0, str.length() - 1);
            }
    }
    /**
     * 清除文件中的table
     *
     * @param content
     *            公告内容
     * @return 字符串结果集
     */
    public static String removeContentStyle(String content) {
            String regEx = "<table(.*?)</table>";
            Pattern p = Pattern.compile(regEx);
            Matcher m = p.matcher(content);
            if (m.find()) {
                    content = m.replaceAll("");
            }
//            String regEx2 = " style=\"([\\s\\S]*?)\"";
//            Pattern p2 = Pattern.compile(regEx2);
//            Matcher m2 = p2.matcher(content);
//            if (m2.find()) {
//                    content = m2.replaceAll("");
//            }
//            String regEx3 = " border=\"(.*?)\"";
//            Pattern p3 = Pattern.compile(regEx3);
//            Matcher m3 = p3.matcher(content);
//            if (m3.find()) {
//                    content = m3.replaceAll(" border=\"1\" ");
//            }
//
//            String regEx4 = " class=.*?\\>";
//            Pattern p4 = Pattern.compile(regEx4);
//            Matcher m4 = p4.matcher(content);
//            if (m4.find()) {
//                    content = m4.replaceAll("\\>");
//            }
//            String regEx5 = "\\<!--(.*?)--\\>";
//            Pattern p5 = Pattern.compile(regEx5);
//            Matcher m5 = p5.matcher(content);
//            if (m5.find()) {
//                    content = m5.replaceAll("");
//            }
//            String regEx6 = "\\<o:p(.*?)/o:p\\>";
//            Pattern p6 = Pattern.compile(regEx6);
//            Matcher m6 = p6.matcher(content);
//            if (m6.find()) {
//                    content = m6.replaceAll("");
//            }
//            String regEx7 = "\\<!(.*?)\\>";
//            Pattern p7 = Pattern.compile(regEx7);
//            Matcher m7 = p7.matcher(content);
//            if (m7.find()) {
//                    content = m7.replaceAll("");
//            }
//            String regEx8 = "\\<font(.*?)\\>";
//            Pattern p8 = Pattern.compile(regEx8);
//            Matcher m8 = p8.matcher(content);
//            if (m8.find()) {
//                    content = m8.replaceAll("");
//            }
            return content;
    }
    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/580860.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新媒体运营-----短视频运营-----PR视频剪辑----软件基础

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1.1 PR软件重置与初始化设置1.2 新建项目及序列设置1.3 PR工作区的管理方法1.4 导入4K超高清视频并与ME配合工作1…

【C语言】编译与链接

1.翻译环境与运行环境 在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境。 1.翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令&#xff08;二进制指令&#xff09; 2.执行环境&#xff0c;它用于实际执行代码 2.翻译环境 那么翻译环境是怎么将源代码…

Linux(文件系统和日志分析)

目录 1.inode & block​编辑 1.1 inode的内容 1.3 inode的号码 1.4 inode的大小 1.5 inode的特殊作用 1.6 模拟inode号被占满 2. 链接文件 3.文件恢复 3.1 修复EXT类型的文件 3.1.1 EXT类型文件恢复步骤 3.2 修复XFS类型的文件 1.inode & block 1.1 in…

算法应用实例:最大子列和问题

给定N个整数的序列{A1,A2,……AN}&#xff0c;求函数的最大值。 分析&#xff1a;求该序列中最大的连续子列和&#xff0c;若函数最后为负数&#xff0c;返回0作为程序结束。 1.算法1 /*命名为MaxSubseqSum1&#xff0c;A[]:输入整数序列&#xff0c;N&#xff1a;整数序列里面…

7-29 删除字符串中的子串

题目链接&#xff1a;7-29 删除字符串中的子串 一. 题目 1. 题目 2. 输入输出样例 3. 限制 二、代码&#xff08;python&#xff09; 1. 代码实现 str1 input().split(\n)[0] str2 input().split(\n)[0] while str2 in str1:str1 str1.replace(str2, "") // 删…

第4篇:创建Nios II工程之Hello_World<三>

Q&#xff1a;接着我们再来完成Nios II软件工程设计部分。 A&#xff1a;从Quartus Tools选择Nios II Software Build Tools for Eclipse&#xff0c;打开Nios II SBT软件&#xff0c;Workspace指定到hello_world工程的software文件夹路径&#xff1b;再从File-->New-->…

使用STM32CubeMX对STM32F4的CAN1/2/3配置及接收中断开启

目录 1. CAN配置1.1引脚&#xff08;STM32F413VGT6-LQFP100&#xff09;1.2 时钟1.3 RCC配置1.4 CAN1配置1.5 CAN2配置1.6 CAN3配置1.7 输出设置 2. CAN代码2.1 CAN初始化2.2 CAN滤波器设置2.3 CAN使能2.4 激活中断2.5 CAN发送函数2.6 CAN回调函数2.7 main之后的代码 1. CAN配置…

数据分析:生存分析原理和应用实例

介绍 生存分析的目的是分析某个时间点的“生存概率”是多少。基于这样的研究目的,需要提供生存数据,它是一种由不同的开始时间和结束时间组成的事件-时间的数据,比如在癌症研究领域,研究手术到死亡的过程、治疗到疾病进展等等。 在开展生存分析前,需要了解什么是删失(c…

二维码门楼牌管理应用平台建设:隐患统计与智能管理

文章目录 前言一、二维码门楼牌管理应用平台概述二、隐患统计功能的重要性三、隐患统计的实现方式四、隐患统计的实践应用五、面临的挑战与未来发展 前言 随着城市管理的不断升级&#xff0c;二维码门楼牌管理应用平台已成为现代城市管理的重要工具。该平台通过集成先进的信息…

WCH RISC CH32V303RCT6 单片机的SDI Printf 虚拟串口功能 类似SEGGER RTT打印功能 简单分析

参考&#xff1a; 有关于 SDI printf 更多的信息和资料吗&#xff1f; 关于 CH32 系列 MCU SDI 虚拟串口功能的使用 【CH32X035 评估板测评】 教你使用 SDI 接口重定向 printf SDI (Serial Data Interface) 是沁恒微电子 RISC-V 内核的私有外设接口,CH32 RISC-V 系列目前提供了…

PDCA循环:持续精进的工具

文章目录 一、什么是PDCA二、PDCA的应用场景三、PDCA在信息系统项目管理中的应用 一、什么是PDCA PDCA循环是由美国质量管理专家沃特阿曼德休哈特&#xff08;Walter A. Shewhart&#xff09;在20世纪30年代提出的&#xff0c;最初用于制造业的质量管理。休哈特博士在构想PDCA…

二极管钳位型三电平SVPWM(羊角波)闭环系统simulink建模与仿真

整理了二极管钳位型三电平SVPWM&#xff08;羊角波&#xff09;闭环系统simulink建模与仿真模型&#xff0c;附赠参考资料。 在二极管钳位型三电平SVPWM中&#xff0c;通过控制逆变器的开关器件&#xff08;IGBT&#xff09;的导通和关断&#xff0c;将输入的直流电压转换为三…

知网怎么查重 知网查重的详细步骤

知网查重八个步骤&#xff1a;1. 访问官网&#xff0c;注册账号。2. 上传待查文档。3. 选择查重规则。4. 选择相似来源库。5. 提交查重任务。6. 等待查重结果。7. 获取查重报告。8. 下载查重报告。 知网查重的详细步骤 第一步&#xff1a;进入知网查重系统 打开浏览器&#x…

怎样将便签软件搬家?便签迁移攻略

便签软件已成为我们日常生活中不可或缺的记录工具。无论是重要的工作内容&#xff0c;还是琐碎的生活事务&#xff0c;我们都会在便签中一一记下。然而&#xff0c;当我们需要更换电脑或其他设备时&#xff0c;如何将这些珍贵的便签内容迁移到新设备上&#xff0c;成为了许多人…

2024全国大学生高新技术竞赛——算法智星挑战赛 解题报告(流水账版) | 珂学家

前言 评价 因为第一届的缘故吧&#xff0c;导致这场比赛异常的简单。所以不太好评价这块。 怎么说呢&#xff1f; 体验有点差 题目难度没有区分度有两题还存在SPJ判定问题&#xff0c;导致赛时没一人过。 题目分布&#xff0c;简单题占大部分&#xff0c;中等级占一小部分&…

Ubuntu查看端口状态

完蛋了&#xff0c;好像动心了&#xff0c;近一周吃啥东西都索然无味&#xff0c;这可如何是好&#xff01;&#xff01;&#xff01;不知道在期待什么&#xff0c;恐惧与窃喜—— 在Ubuntu系统中&#xff0c;查看某个端口是否被放行&#xff08;即允许流量通过&#xff09;&am…

【JAVA进阶篇教学】第六篇:Java线程中状态

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第六篇&#xff1a;Java线程中状态。 理解并掌握线程的休眠、停止和挂起等操作是多线程编程中的重要内容。下面我将详细说明这些操作&#xff0c;并提供相应的代码案例。 目录 一、线程休眠&#xff08;Thread Slee…

一个早安寄语打卡的小程序技术分享

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 1.早起打卡还能赚钱&#xff1f; 是的&#xff0c;你没有听错&#xff0c;最近发现了个非常有意思的小程序&#xff0c;主要是让用户早起早睡&#xff0c;然后每天进行打卡操作的。 当然&…

【KG+RAG 论文】医学知识图谱检索增强 LLM 的框架 —— KG-RAG

论文&#xff1a;Biomedical knowledge graph-enhanced prompt generation for large language models ⭐⭐⭐ Code&#xff1a;github.com/BaranziniLab/KG_RAG 文章目录 论文速读模型效果总结 论文速读 这篇论文提出了 KG-RAG 的框架&#xff0c;使用医学知识图谱&#xff0…

黑马面试篇

课程地址&#xff1a;新版Java面试专题视频教程&#xff0c;java八股文面试全套真题深度详解&#xff08;含大厂高频面试真题&#xff09;_哔哩哔哩_bilibili 课程名称&#xff1a;新版Java面试专题视频教程&#xff0c;java八股文面试全套真题深度详解&#xff08;含大厂高频…