Java 串口通信—收发,监听数据(代码实现)
一、串口通信与串行通信的原理
串行通信是指仅用一根接收线和一根发送线,将数据以位进行依次传输的一种通讯方式,每一位数据占据一个固定的时间长度。
串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节的通信方式。
串口通信时首先要约定好帧格式与波特率,并且串口通信采用TTL逻辑(Transistor-Transistor Logic)
是指晶体管-晶体管逻辑。
TTL逻辑门的标准输出状态是:
高电平(逻辑“1”或HIGH):典型值为+2.4V至+5V(对于标准5V电源供电的TTL),代表有效信号。
低电平(逻辑“0”或LOW):典型值接近于地电压(0V至+0.4V),代表无效信号。
这种通信方式抗干扰能力弱,下图中,静电让某一个低电平变高,就会导致通信距离很短,越1米。
所以为了提示通信的稳定性与距离,产生了由美国制订的推荐标准RS232、RS485,都是在基础串口通信的基础上加了特定的电平转换芯片改变电压传输值。
串口通信主要可分为232、485、422三种通信方式。
232通信
232通信主要是由RX、TX、GND三根线组成。RX接TX,TX接RX,GND接GND。发送和接收由不同的线路处理,所以能够同时进行发送和接收数据,因此232是全双工通信。
485通信
为了解决232通信距离受限问题,于是有了485通信。 485通信只需要+、-两根线(也叫A、B两根线),A、B两根线的差分电平信号就是作为数据信号传输。发送和接收都用这两根线,每次只能发送数据或者接收数据,因此485是半双工通信。
422通信
422通信兼具232与485的特点,既能实现全双工通信,又能增大传输距离。422也常被标注为485-4,而485被标注为485-2。因为485-2是2根线,485-4是4根线。
并行和串行的区别:
-
并行传输: 多根线路传输,每条物理线代表一个比特位,可以同时发送和接受多个字节;
-
串行传输: 只用一条线路传输,逐位传输,字节内允许出现延迟(如开始或结束等),而每个字节之间必须有完整的停止和起始位置。
同步传输和异步传输的差别:
-
同步传输:在知道对方状态下进行全双工传输,需要调节系统时钟,使得传送速度不超过缓存容量,并保持包络上均衡。
-
异步传输:既能针对字符流,也可针对比特流。异步传输没有明确定义的“帧”模式,因此不需要同步时钟,但会增加一个帧同步域,用于在接收端恢复字节边界,并通过位数逐个地进行帧的识别。
在实际应用中,串口通常使用异步技术来发送和接收数据。异步传输可以按需动态调整数据传输速率,以便快速响应用户操作或自动控制事件的发生。
二、Java 实现串口通信
准备工作
要想使用串口包进行串口通信,除了设置好环境变量之外,还要准备对应的串口通信的jar包
1. 下载对应版本的rxtx 解压后得到三个文件 rxtxParallel.dll、rxtxSerial.dll、RXTXcomm.jar/
下载地址如下:RXTX for Java (fizzed.com)
2. 将rxtxParallel.dll、rxtxSerial.dll 放进当前使用的jdk的bin目录( jdk版本必须与下载的rxtx一致 ,区分32位/64位 AMD/IA)
3. (windows x64系统可以将当前项目libs下的 rxtxParallel.dll、rxtxSerial.dll 直接放入jdk下的bin目录)
4. 需要将libs下的RXTXcomm.jar加入项目依赖,将javax.usb.properties复制到 JRE\lib或者JDK\lib.
<dependency><groupId>org.rxtx</groupId><artifactId>rxtx</artifactId><version>2.2</version><scope>system</scope><systemPath>${project.basedir}/src/main/resources/lib/RXTXcomm.jar</systemPath>
</dependency>
说明:(如果没有正常引入将会出现这个错误)
代码实现
package com.ss.serialport.controller;import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;public class SerialPortTool {public static void main(String[] args) {// 查询串口findSystemAllComPort();// //发送16进制数据——实际应用中串口通信传输的数据,大都是 16 进制String hexStrCode = "455A432F5600";SerialPort serialPort = SerialPortTool.openComPort(null, 38400, 8, 1, 0);// 设置串口监听SerialPortTool.setListenerToSerialPort(serialPort, new SerialPortEventListener() {@Overridepublic void serialEvent(SerialPortEvent arg0) {if (arg0.getEventType() == SerialPortEvent.DATA_AVAILABLE) {//数据通知byte[] bytes = SerialPortTool.readData(serialPort);System.out.println("收到的数据长度:" + bytes.length);System.out.println("收到的数据:" + new String(bytes));}}});new Thread(new Runnable() {@Overridepublic void run() {int i = 1;while (i < 1000) {byte[] bytes = hexStrCode.getBytes();SerialPortTool.sendDataToComPort(serialPort, bytes);//发送数据i++;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}/*** 查找电脑上所有可用 com 端口** @return 可用端口名称列表,没有时 列表为空*/public static final ArrayList<String> findSystemAllComPort() {/*** getPortIdentifiers:获得电脑主板当前所有可用串口*/Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();ArrayList<String> portNameList = new ArrayList<>();/*** 将可用串口名添加到 List 列表*/System.out.println("===========串口信息start==============");while (portList.hasMoreElements()) {CommPortIdentifier commPortIdentifier = portList.nextElement();StringBuffer returnStr = new StringBuffer();String portName = commPortIdentifier.getName();//名称如 COM1、COM2....String isOwner = String.valueOf(commPortIdentifier.isCurrentlyOwned());returnStr.append(isOwner).append("\t 占用情况:").append(isOwner);System.out.println(returnStr);portNameList.add(portName);}System.out.println("===========串口信息end==============");return portNameList;}/*** 打开电脑上指定的串口** @param portName 端口名称,如 COM1,为 null 时,默认使用电脑中能用的端口中的第一个* @param b 波特率(baudrate),如 9600* @param d 数据位(datebits),如 SerialPort.DATABITS_8 = 8* @param s 停止位(stopbits),如 SerialPort.STOPBITS_1 = 1* @param p 校验位 (parity),如 SerialPort.PARITY_NONE = 0* @return 打开的串口对象,打开失败时,返回 null*/public static final SerialPort openComPort(String portName, int b, int d, int s, int p) {CommPort commPort = null;try {//当没有传入可用的 com 口时,默认使用电脑中可用的 com 口中的第一个if (portName == null || "".equals(portName)) {List<String> comPortList = findSystemAllComPort();if (comPortList != null && comPortList.size() > 0) {portName = comPortList.get(0);}}System.out.println("开始打开串口:portName=" + portName + ",baudrate=" + b + ",datebits=" + d + ",stopbits=" + s + ",parity=" + p);//通过端口名称识别指定 COM 端口CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);/*** open(String TheOwner, int i):打开端口* TheOwner 自定义一个端口名称,随便自定义即可* i:打开的端口的超时时间,单位毫秒,超时则抛出异常:PortInUseException if in use.* 如果此时串口已经被占用,则抛出异常:gnu.io.PortInUseException: Unknown Application*/commPort = portIdentifier.open(portName, 5000);/*** 判断端口是不是串口* public abstract class SerialPort extends CommPort*/if (commPort instanceof SerialPort) {SerialPort serialPort = (SerialPort) commPort;/*** 设置串口参数:setSerialPortParams( int b, int d, int s, int p )* b:波特率(baudrate)* d:数据位(datebits),SerialPort 支持 5,6,7,8* s:停止位(stopbits),SerialPort 支持 1,2,3* p:校验位 (parity),SerialPort 支持 0,1,2,3,4* 如果参数设置错误,则抛出异常:gnu.io.UnsupportedCommOperationException: Invalid Parameter* 此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用*/serialPort.setSerialPortParams(b, d, s, p);System.out.println("打开串口 " + portName + " 成功...");return serialPort;} else {System.out.println("当前端口 " + commPort.getName() + " 不是串口...");}} catch (NoSuchPortException e) {e.printStackTrace();} catch (PortInUseException e) {System.out.println("串口 " + portName + " 已经被占用,请先解除占用...");e.printStackTrace();} catch (UnsupportedCommOperationException e) {System.out.println("串口参数设置错误,关闭串口,数据位[5-8]、停止位[1-3]、验证位[0-4]...");e.printStackTrace();if (commPort != null) {//此时必须关闭串口,否则下次 portIdentifier.open 时会打不开串口,因为已经被占用commPort.close();}}System.out.println("打开串口 " + portName + " 失败...");return null;}/*** 往串口发送数据** @param serialPort 串口对象* @param orders 待发送数据*/public static void sendDataToComPort(SerialPort serialPort, byte[] orders) {OutputStream outputStream = null;try {if (serialPort != null) {outputStream = serialPort.getOutputStream();outputStream.write(orders);outputStream.flush();System.out.println("往串口 " + serialPort.getName() + " 发送数据:" + Arrays.toString(orders) + " 完成...");} else {System.out.println("gnu.io.SerialPort 为null,取消数据发送...");}} catch (IOException e) {e.printStackTrace();} finally {if (outputStream != null) {try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 从串口读取数据** @param serialPort 要读取的串口* @return 读取的数据*/public static byte[] readData(SerialPort serialPort) {InputStream is = null;byte[] bytes = null;try {is = serialPort.getInputStream();//获得串口的输入流int bufflenth = is.available();//获得数据长度while (bufflenth != 0) {bytes = new byte[bufflenth];//初始化byte数组is.read(bytes);bufflenth = is.available();}} catch (IOException e) {e.printStackTrace();} finally {try {if (is != null) {is.close();is = null;}} catch (IOException e) {e.printStackTrace();}}return bytes;}/*** 给串口设置监听** @param serialPort* @param listener*/public static void setListenerToSerialPort(SerialPort serialPort, SerialPortEventListener listener) {try {//给串口添加事件监听serialPort.addEventListener(listener);} catch (TooManyListenersException e) {e.printStackTrace();}serialPort.notifyOnDataAvailable(true);//串口有数据监听serialPort.notifyOnBreakInterrupt(true);//中断事件监听}/*** 关闭串口** @param serialPort 待关闭的串口对象*/public static void closeComPort(SerialPort serialPort) {if (serialPort != null) {serialPort.close();System.out.println("关闭串口 " + serialPort.getName());}}/*** 16进制字符串转十进制字节数组* 这是常用的方法,如某些硬件的通信指令就是提供的16进制字符串,发送时需要转为字节数组再进行发送** @param strSource 16进制字符串,如 "455A432F5600",每两位对应字节数组中的一个10进制元素* 默认会去除参数字符串中的空格,所以参数 "45 5A 43 2F 56 00" 也是可以的* @return 十进制字节数组, 如 [69, 90, 67, 47, 86, 0]*/public static byte[] hexString2Bytes(String strSource) {if (strSource == null || "".equals(strSource.trim())) {System.out.println("hexString2Bytes 参数为空,放弃转换.");return null;}strSource = strSource.replace(" ", "");int l = strSource.length() / 2;byte[] ret = new byte[l];for (int i = 0; i < l; i++) {ret[i] = Integer.valueOf(strSource.substring(i * 2, i * 2 + 2), 16).byteValue();}return ret;}}
整合成串口工具类 :
package com.ss.serialport.utils;import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;/*** @ClassName DLSC_SerialPort* @Description 串口工具类 :打开串口 ;接受数据 ;发送数据* @Version 1.0*/
public class DLSC_SerialPort {private SerialPort serialPort;private InputStream inputStream;private OutputStream outputStream;private BlockingQueue<String> receivedDataQueue = new LinkedBlockingQueue<>();private volatile boolean isRunning = true;private void connect(String portName) throws Exception {// 获取串口通信端口实例CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(portName);if (portId.isCurrentlyOwned()) {System.err.println("Error: Port is currently in use");} else {// 打开端口,并获取输入、输出流serialPort = (SerialPort) portId.open("SerialCommExample", 2000);inputStream = serialPort.getInputStream();outputStream = serialPort.getOutputStream();// 设置串口参数serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);// 启动读取数据的线程Thread readThread = new Thread(() -> {try {while (isRunning) {int available = inputStream.available();if (available > 0) {byte[] bytes = new byte[available];inputStream.read(bytes);String data = new String(bytes, "UTF-8");receivedDataQueue.put(data); // 将数据放入队列}Thread.sleep(100); // 等待一段时间再检查是否有新数据}} catch (IOException | InterruptedException e) {e.printStackTrace();}});readThread.start();}}private void sendData(String data) throws IOException {if (outputStream != null) {outputStream.write(data.getBytes("UTF-8"));outputStream.flush(); // 确保数据被发送出去}}private String receiveData(long timeout) throws InterruptedException {return receivedDataQueue.poll(timeout, TimeUnit.MILLISECONDS); // 尝试从队列中获取数据,超时则返回null}private void disconnect() throws Exception {isRunning = false; // 设置标志位以停止读取数据的线程if (serialPort != null) {serialPort.removeEventListener();serialPort.close();}}public static void send (String msg) {DLSC_SerialPort example = new DLSC_SerialPort();try {// 连接到串口example.connect("COM3"); // 替换为你的串口名称// 发送数据example.sendData(msg + "\r\n");// 断开连接example.disconnect();} catch (Exception e) {e.printStackTrace();}}public static Double sendAndReceives(String msg) {DLSC_SerialPort example = new DLSC_SerialPort();try {// 连接到串口example.connect("COM1"); // 替换为你的串口名称// 发送数据example.sendData(msg + "\r\n");// 等待并接收数据String receivedData = example.receiveData(5000); // 等待最多5秒来获取数据if (receivedData != null) {Double backData = Double.valueOf(receivedData);System.out.println("Received data: " + backData);return backData;} else {System.out.println("No data received within the timeout period.");}// 断开连接example.disconnect();} catch (Exception e) {e.printStackTrace();}return null;}// public static String sendAndReceive(String msg) {
//
// SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
// ArrayList<String> port = serialPortUtil.findPort();
// if (port != null && !port.isEmpty()) {
// System.out.println("没有发现任何端口");
// }
// String portName = port.get(2);
// SerialPort serialPort = serialPortUtil.openPort(
// portName, 9600, 8, 1, 0);
// if (serialPort == null) {
// System.out.println("打开串口(" + portName + ")失败");
// }
// System.out.println("成功连接串口:" + portName);serialPortUtil.sendToPort(serialPort, "SOUR:VOLT 28\r\n".getBytes());
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// serialPortUtil.sendToPort(serialPort, "SOUR:CURR:LIMIT:HIGH?\r\n".getBytes());
// byte[] bytes = serialPortUtil.readFromPort(serialPort);
// if (bytes != null) {
// return new String(bytes);
// }
// serialPortUtil.closePort(serialPort);
// return null;
// }// public static String sendAndReceive(String msg) {
//
// SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();
// ArrayList<String> port = serialPortUtil.findPort();
// if (port != null && !port.isEmpty()) {
// System.out.println("没有发现任何端口");
// }
// String portName = port.get(0);
// SerialPort serialPort = serialPortUtil.openPort(
// portName, 9600, 8, 1, 0);
// if (serialPort == null) {
// System.out.println("打开串口(" + portName + ")失败");
// }
// System.out.println("成功连接串口:" + portName);serialPortUtil.sendToPort(serialPort, "SOUR:VOLT 28\r\n".getBytes());
// try {
// Thread.sleep(6000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// serialPortUtil.sendToPort(serialPort, "SOUR:CURR:LIMIT:HIGH?\r\n".getBytes());
// byte[] bytes = serialPortUtil.readFromPort(serialPort);
// if (bytes != null) {
// return new String(bytes);
// }
// System.out.println(serialPort);
// serialPortUtil.closePort(serialPort);
// return null;
// }public static String sendAndReceive(String msg) {SerialPortUtil serialPortUtil = SerialPortUtil.getSerialPortUtil();ArrayList<String> port = serialPortUtil.findPort();System.out.println(port);if (port == null || port.isEmpty()) {System.out.println("没有发现任何端口");return null;}String portName = port.get(0);SerialPort serialPort = serialPortUtil.openPort(portName, 9600, 8, 1, 0);if (serialPort == null) {System.out.println("打开串口(" + portName + ")失败");return null;}System.out.println("成功连接串口:" + portName);try {// serialPortUtil.sendToPort(serialPort, "SOUR:VOLT 28\r\n".getBytes());Thread.sleep(6000);serialPortUtil.sendToPort(serialPort, "SOUR:CURR:LIMIT:HIGH?\r\n".getBytes());byte[] bytes = serialPortUtil.readFromPort(serialPort);if (bytes != null) {return new String(bytes);} else {System.out.println("未读取到任何数据");return null;}} catch (InterruptedException e) {e.printStackTrace();return null;} finally {// 确保串口在所有情况下都关闭serialPortUtil.closePort(serialPort);}}
}
相关文章:

Java 串口通信—收发,监听数据(代码实现)
一、串口通信与串行通信的原理 串行通信是指仅用一根接收线和一根发送线,将数据以位进行依次传输的一种通讯方式,每一位数据占据一个固定的时间长度。 串口通信(Serial Communications)的概念非常简单,串口按位&#x…...
fileinput pdf编辑初始化预览
var $fileLinkInput $(#file_link_full); $fileLinkInput.fileinput({language: zh,uploadUrl: <?php echo Yii::$app->urlManager->createUrl([file/image, type > work_file]);?>,initialPreview: [defaultFile],initialPreviewAsData: true,initialPrevie…...

微信支付开发-需求整理及需求设计
一、客户要求 1、通过唤醒机器人参与答题项,机器人自动获取题目,用户进行答题; 2、用户答对题数与后台设置的一样或者更多,则提醒用户可以领取奖品,但是需要用户支付邮费; 3、用户在几天之内不能重复领取奖…...
vs code: pnpm : 无法加载文件 C:\Program Files\nodejs\pnpm.ps1,因为在此系统上禁止运行脚本
在visual studio code运行pnpm出错: pnpm : 无法加载文件 C:\Program Files\nodejs\pnpm.ps1,因为在此系统上禁止运行脚本 解决方案: 到C:\Program Files\nodejs文件夹下删除pnpm.ps1即可。 C:\Program Files\nodejs改成你自己的路径...

web测试必备技能:浏览器兼容性测试
如今,市面上的浏览器种类越来越多(尤其是在平板和移动设备上),这就意味着你所测试的站点需要在这些你声称支持浏览器上都能很好的工作。 同时,主流浏览器(IE,Firefox,Chrome&#x…...

《数据资产管理核心技术与应用》首次大型赠书活动圆满结束
《数据资产管理核心技术与应用》是清华大学出版社出版的一本图书,作者为张永清等著,在2024.9.11号晚上20:00,本书作者张永清联合锋哥聊数仓公众号和清华大学出版社一起,向各大大数据技术爱好者通过三轮互动活动赠送了3本正版图书。…...
vue在一个组件引用其他组件
在vue一个组件中引用另一个组件的步骤 必须在script中导入要引用的组件需要在export default的components引用导入的组件(这一步经常忘记)在template使用导入的组件<script><!-- 第一步,导入--> import Vue01 from "@/components/Vue01.vue";...

软件测试学习笔记丨Postman实战练习
本文转自测试人社区,原文链接:https://ceshiren.com/t/topic/32096#h-22 二、实战练习 2.1 宠物商店接口文档分析 接口文档:http://petstore.swagger.io ,这是宠物商店接口的 swagger 文档。 2.1.1 什么是 swagger Swagger 是…...

kubernetes微服务基础及类型
目录 1 什么是微服务 2 微服务的类型 3 ipvs模式 ipvs模式配置方式 4 微服务类型详解 4.1 ClusterIP 4.2 ClusterIP中的特殊模式headless 4.3 nodeport 4.4 metalLB配合loadbalance实现发布IP 1 什么是微服务 用控制器来完成集群的工作负载,那么应用如何暴漏出去&…...

linux-L3_linux 查看进程(node-red)
linux 查看进程 以查看进程node-red为例 ps aux | grep node-red...

区块链之变:揭秘Web3对互联网的改变
传统游戏中,玩家的虚拟资产(如角色、装备)通常由游戏公司控制,玩家无法真正拥有这些资产或进行交易。而在区块链游戏中,虚拟资产通过去中心化技术记录在区块链上,玩家对其拥有完全的所有权,并能…...

SAP B1 Web Client MS Teams App集成连载一:先决条件/Prerequisites
一、先决条件/Prerequisites 在设置 SAP Business One 应用之前,确保您已具备以下各项:Before you set up the SAP Business One app, make sure you have acquired the following: 1.Microsoft Teams 管理员账户/A Microsoft Teams admin account 您需…...

去除单细胞数据中环境游离的RNA污染-decontX工具学习
DecontX 是一种用于单细胞 RNA 测序数据的去除环境污染物(decontamination)的工具,主要用于减少由细胞外RNA造成的污染效应。 开发者在20年的文章中已经把这个工具适用的情况说的非常清楚了:简单来说就是基于微流控的单细胞技术会…...

Games101图形学笔记——光栅化
这里写目录标题 Rasterization光栅化屏幕空间隔行扫描三角形采样采样产生的问题反走样处理方法:采样前模糊 频率,时域傅里叶级数展开傅里叶变换 滤波高通滤波低通滤波 卷积卷积的一些定理 反走样MSAA(Multisample Anti-Aliasing)多…...

2024年汉字小达人区级自由报名的几个最新问题和真题练一练
2024年第十一届汉字小达人的区级活动的时间9月25-30日正式开赛,还有不到两周。 今天继续回答家长和孩子们的几个问题,并给大家看看一些真题,让孩子对汉字小达人的题型和比赛有直观的了解,从而更好地备考。 本专题在比赛前持续更…...

从简单分析到智能问数,Smartbi AIChat让数据回归业务
大数据产业创新服务媒体 ——聚焦数据 改变商业 在某科技公司,资深数据分析师李晨(化名)正忙于分析新产品的市场表现。面对传统自助式BI工具,李晨在功能界面中手动设置各种查询条件,进行了一番复杂的拖拉拽操作&#…...

基于SpringBoot+Vue+MySQL的考编论坛网站
系统展示 用户前台界面 管理员后台界面 系统背景 在当前信息化高速发展的时代,考编已成为众多求职者的重要选择。然而,备考过程中信息获取、经验交流及资源分享的需求日益凸显。基于SpringBoot、Vue.js与MySQL构建的考编论坛网站应运而生,旨在…...

SpringSecurity剖析
1、SpringSecurity 入门 1.1、简介 Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。Spring Security是一个框架,致力于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Sp…...
一文搞懂 Flink Graph 构建过程源码
一文搞懂 Flink Graph 构建过程 1. StreamGraph构建过程1.1 transform(): 构建的核心1.2 transformOneInputTransform1.3 构造顶点1.4 构造边1.5 transformSource1.6 transformPartition1.7 transformSink 1. StreamGraph构建过程 链接: 一文搞懂 Flink 其他重要源码点击我 e…...

【spring】IDEA 新建一个spring boot 项目
参考新建项目-sprintboot 选择版本、依赖,我选了一堆 maven会重新下载一次么?...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
Python爬虫实战:研究Restkit库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...

Python环境安装与虚拟环境配置详解
本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南,适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者,都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...
拟合问题处理
在机器学习中,核心任务通常围绕模型训练和性能提升展开,但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正: 一、机器学习的核心任务框架 机…...
java+webstock
maven依赖 <dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.3.5</version></dependency><dependency><groupId>org.apache.tomcat.websocket</groupId&…...
【Pandas】pandas DataFrame dropna
Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值(NaN)DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充(即“下一个有效观测值”)…...