C# SerialPort 使用详解
总目录
前言
在工业控制、物联网、嵌入式开发等领域,串口通信(Serial Port Communication)是连接串行设备(如条码扫描器、GPS接收器等)与计算机的重要手段。C# 提供了内置的 SerialPort
类,简化了串口开发的流程。本文将详细介绍如何在C#中使用SerialPort
类进行串口通信。
一、什么是 SerialPort?
1. 定义
System.IO.Ports.SerialPort
类(简称 SerialPort
)是 .NET 框架中用于串口通信的核心类,它提供了对串行端口的访问,允许我们进行数据的读写、配置串口参数以及处理事件等操作。
2. 串行通信简介
串口通信(Serial Communication)是通过单条数据线按顺序传输数据的通信方式,具有接线简单、成本低廉的特点。在工业控制、物联网设备、传感器等领域广泛应用,波特率范围常见为 9600 9600 9600 到 115200 115200 115200。
- 在工业自动化、嵌入式系统开发等场景中,串口通信(Serial Communication)仍是硬件交互的核心技术之一。
- 串行通信是一种数据按位顺序传输的通信方式,常用于连接各种串行设备。
- C# 通过 System.IO.Ports.SerialPort 类为开发者提供了简洁高效的串口操作接口,支持参数配置、数据读写及事件处理等功能。
3. SerialPort
核心功能
- 端口配置参数:波特率、数据位、校验位、停止位等。
- 数据读写操作:同步或异步发送/接收数据。
- 事件驱动通信:通过
DataReceived
事件实时响应数据到达。
4. 典型应用场景
- 工业设备通信
- 传感器数据采集
- 嵌入式系统交互
二、常用的属性和方法
1. 常用属性
属性名 | 类型/说明 |
---|---|
PortName | string 串口名称(如 COM1 、COM3 )。 |
BaudRate | int 波特率,表示数据传输速率。常用的有 9600 、19200 、38400 、57600 以及115200 等 |
Parity | Parity 奇偶校验类型如 None 无奇偶校验、Even 偶检验、Odd 奇检验。 |
DataBits | int 数据位数。常见数据位为8位,如需要特别设置,还可设置位5位,6位,7位 |
StopBits | StopBits 停止位数如 None 不使用停止位One 1个停止位、Two 2个停止位、OnePointFive 1.5个停止位)。 |
Handshake | Handshake 握手协议(如 None 、RequestToSend 、XOnXOff )。 |
Encoding | Encoding 数据编码方式(如 Encoding.UTF8 )。 |
ReadTimeout | int 读取操作超时时间(毫秒),默认为 InfiniteTimeout 。 |
WriteTimeout | int 写入操作超时时间(毫秒),默认为 InfiniteTimeout 。 |
IsOpen | bool 表示串口是否已打开。 |
NewLine | string 定义行结束符(如 "\r\n" ),用于 ReadLine() 和 WriteLine() 。 |
DtrEnable | bool 控制数据终端就绪(DTR)信号状态。 |
RtsEnable | bool 控制请求发送(RTS)信号状态。 |
ReceivedBytesThreshold | int 触发 DataReceived 事件的最小字节数。 |
2. 常用方法
方法名 | 说明 |
---|---|
Open() | 打开串口。 |
Close() | 关闭已打开的串口。 |
Read(byte[] buffer, int offset, int count) | 从串口读取指定字节数到缓冲区。 |
ReadByte() | 读取单个字节(返回 int ,范围 0-255 ,失败返回 -1 )。 |
ReadLine() | 读取一行数据,直到遇到 NewLine 定义的结束符。 |
ReadExisting() | 读取接收缓冲区中所有可用数据(不阻塞)。 |
Write(string text) | 写入字符串到串口(自动按 Encoding 编码)。 |
Write(byte[] buffer, int offset, int count) | 写入字节数组到串口。 |
DiscardInBuffer() | 清空输入缓冲区中的数据。 |
DiscardOutBuffer() | 清空输出缓冲区中的数据。 |
3. 常用事件
事件名 | 说明 |
---|---|
DataReceived | 当接收到数据且字节数达到 ReceivedBytesThreshold 时触发。 |
ErrorReceived | 当串口发生错误(如奇偶校验错误)时触发。 |
4. 其他重要属性(扩展)
属性名 | 类型/说明 |
---|---|
BytesToRead | int 接收缓冲区中已接收的字节数。 |
BytesToWrite | int 输出缓冲区中待发送的字节数。 |
ReadBufferSize | int 设置输入缓冲区大小(默认 4096 )。 |
WriteBufferSize | int 设置输出缓冲区大小(默认 2048 )。 |
三、SerialPort 基础
1. 添加命名空间引用
在使用SerialPort
类之前,需要先添加对System.IO.Ports
命名空间的引用:
using System.IO.Ports;
2. 初始化与参数配置
串口通信的核心是正确配置参数,确保与硬件设备匹配,否则通信失败。
1)方式1:构造函数
using System.IO.Ports;// 创建对象并指定端口名称(如COM3)
SerialPort serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
2)方式2:属性配置
// 可选:手动设置参数(适用于动态配置)
SerialPort serialPort = new SerialPort();
serialPort.PortName = "COM3"; // 端口号
serialPort.BaudRate = 9600; // 波特率
serialPort.Parity = Parity.None; // 校验位
serialPort.DataBits = 8; // 数据位
serialPort.StopBits = StopBits.One; // 停止位
3. 打开与关闭串口
1)打开串口
在进行数据传输之前,需要打开串行端口:
serialPort.Open(); // 打开串口
优化一下:加上try catch
做异常处理
try
{if (!serialPort.IsOpen){serialPort.Open();Console.WriteLine("端口已打开");}
}
catch (Exception ex)
{Console.WriteLine($"打开失败:{ex.Message}");
}
2)关闭串口
数据传输完成后,应及时关闭串行端口。务必在程序退出前调用Close
serialPort.Close(); // 关闭端口
优化一下:加上try catch
做异常处理
try
{if (serialPort.IsOpen){// 关闭端口serialPort.Close();Console.WriteLine("端口已关闭");// 销毁serialPort对象serialPort.Dispose();}
}
catch (Exception ex)
{Console.WriteLine($"关闭失败:{ex.Message}");
}
4. 读取和写入数据
1)写入数据
▶ 写入字符串数据
- 使用
Write()
方法:将指定的字符串写入串行端口。 - 使用
WriteLine
方法:将指定的字符串和SerialPort.NewLine
值写入串行端口。
serialPort.Write("Hello, Serial!");// 自动添加换行符:发送字符串并添加换行符(WriteLine)
serialPort.WriteLine("Hello, Serial Port!");
▶ 写入字节流(字节数组)数据
// 发送字节数组
byte[] data = Encoding.UTF8.GetBytes("Test Data");
serialPort.Write(data, 0, data.Length);byte[] data = { 0x01, 0xFF, 0xAB }; // 十六进制数据
serialPort.Write(data, 0, data.Length); // 发送字节
2)读取数据
可以通过Read()
、ReadLine()
等方法从串口读取数据。
// 读取指定字节数
byte[] buffer = new byte[1024];
int bytesRead = serialPort.Read(buffer, 0, buffer.Length);
string received = Encoding.UTF8.GetString(buffer, 0, bytesRead);// 读取一行数据(依赖 NewLine 配置)
string line = serialPort.ReadLine();
5. 处理数据接收事件
通过 DataReceived
事件实时接收串口数据。当有数据到达时,DataReceived
事件会被触发。可以通过注册该事件来实时处理接收到的数据:
1)使用方式1
// 注册 DataReceived 事件
serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{SerialPort sp = (SerialPort)sender;string received = sp.ReadExisting(); // 读取所有可用数据Console.WriteLine($"Received: {received}");
}
2)使用方式2
serialPort.DataReceived += SerialPort_DataReceived;
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{//首先实例化一个字节数组// 字节数组的大小:通过BytesToRead 属性,获取得到缓冲区中数据的字节数byte[] buffer = new byte[serialPort.BytesToRead];//再通过 Read() 方法 读取缓存区内全部数据,并将数据写入字节数组中serialPort.Read(buffer, 0, buffer.Length);// 解码string received = Encoding.ASCII.GetString(buffer); Console.WriteLine(received);
}
3)使用方式3
serialPort.DataReceived += (sender, e) =>
{if (e.EventType == SerialData.Chars){byte[] buffer = new byte[serialPort.BytesToRead];serialPort.Read(buffer, 0, buffer.Length);string data = Encoding.ASCII.GetString(buffer);Console.WriteLine($"收到数据:{data}");}
};
以上三种方式,基本原理一致,只是部分的读取数据方式和事件定义的方式稍有不同而已。
6. 完整示例
示例1:简单示例
using System;
using System.IO.Ports;
using System.Windows.Forms;public class SerialPortDemo
{//配置并创建SerialPort实例private SerialPort sp = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);public void Start(){try{// 注册数据接收事件sp.DataReceived += DataReceivedHandler;// 打开串口sp.Open();//写入数据sp.WriteLine("Start Communication");}catch (Exception ex){MessageBox.Show($"初始化失败:{ex.Message}");}}// 接收数据private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e){// 读取数据string data = sp.ReadExisting();Console.WriteLine($"实时数据:{data}");}// 关闭端口public void Stop() => sp.Close();
}
示例2:WinForm 示例
以下是一个完整的示例,展示如何在C#中使用SerialPort
类进行串口通信。
using System;
using System.IO.Ports;
using System.Windows.Forms;namespace SerialPortExample
{public partial class MainForm : Form{private SerialPort serialPort;public MainForm(){InitializeComponent();InitializeSerialPort();}private void InitializeSerialPort(){serialPort = new SerialPort();serialPort.PortName = "COM1";serialPort.BaudRate = 9600;serialPort.Parity = Parity.None;serialPort.DataBits = 8;serialPort.StopBits = StopBits.One;serialPort.Handshake = Handshake.None;serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);}private void btnOpen_Click(object sender, EventArgs e){try{if (!serialPort.IsOpen){serialPort.Open();MessageBox.Show("串口已打开");}}catch (Exception ex){MessageBox.Show("打开串口时出错: " + ex.Message);}}private void btnSend_Click(object sender, EventArgs e){if (serialPort.IsOpen){string message = txtSend.Text;serialPort.WriteLine(message);txtReceive.AppendText("发送: " + message + Environment.NewLine);}else{MessageBox.Show("请先打开串口");}}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){SerialPort sp = (SerialPort)sender;string indata = sp.ReadExisting();this.Invoke(new Action(() =>{txtReceive.AppendText("接收: " + indata);}));}private void btnClose_Click(object sender, EventArgs e){if (serialPort.IsOpen){serialPort.Close();MessageBox.Show("串口已关闭");}}}
}
示例3:扫码枪数据接收
SerialPort port = new("COM3", 115200, Parity.None, 8, StopBits.One);
port.DataReceived += (s, e) =>
{byte[] barcode = new byte[port.BytesToRead];port.Read(barcode, 0, barcode.Length);// 解析扫码枪数据(通常以回车结尾)if (barcode.Last() == 0x0D) {string code = Encoding.ASCII.GetString(barcode);ProcessBarcode(code);}
};
四、SerialPort 进阶
1. 高级参数配置
1)配置超时时间
防止长时间阻塞(单位:毫秒)。
// 设置读取超时为 1000ms
serialPort.ReadTimeout = 1000;
// 设置写入超时
serialPort.WriteTimeout = 500;
2)缓冲区设置
ReceivedBytesThreshold
:指定触发 DataReceived
事件的字节阈值,即触发 DataReceived
事件的最小字节数。
serialPort.ReceivedBytesThreshold = 2; //默认值 为 1
3)其余参数配置
sp.Encoding = Encoding.ASCII; // 编码格式
sp.NewLine = "\r\n"; // 换行符定义
2. 获取所有可用 COM 端口
可以通过SerialPort.GetPortNames()
方法获取系统中所有可用的串行端口名称:
// 获取所有可用 COM 端口
string[] ports = SerialPort.GetPortNames();
foreach (var port in ports)
{Console.WriteLine(port);
}
3. ErrorReceived事件
当串行通信中发生错误(如帧错误/缓冲区溢出)时,ErrorReceived
事件会被触发:
serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
private static void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{if ((e.EventType & SerialError.Frame) == SerialError.Frame){Console.WriteLine("Frame error detected.");}if ((e.EventType & SerialError.Overrun) == SerialError.Overrun){Console.WriteLine("Overrun error detected.");}if ((e.EventType & SerialError.RXParity) == SerialError.RXParity){Console.WriteLine("Parity error detected.");}
}
sp.ErrorReceived += (sender, e) =>
{Console.WriteLine($"错误类型:{e.EventType}");
};
4. 异常处理
使用try-catch
块捕获和处理可能的异常,确保程序的稳定性:
try
{serialPort.Open();serialPort.WriteLine("Hello, Serial Port!");serialPort.Close();
}
catch (Exception ex)
{Console.WriteLine("Error: " + ex.Message);
}
// 常见异常类型
try
{// 串口操作代码
}
catch (UnauthorizedAccessException ex)
{Console.WriteLine("端口访问被拒绝");
}
catch (TimeoutException ex)
{Console.WriteLine("操作超时");
}
catch (IOException ex)
{Console.WriteLine("I/O错误");
}
5. 跨线程处理
为了能够实时响应串口接收到的数据,可以使用DataReceived
事件。需要注意的是,该事件在单独的线程中触发,若要更新UI控件,涉及到跨线程,需要使用Invoke
方法。
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{SerialPort sp = (SerialPort)sender;string received = sp.ReadExisting();// 数据接收后,通过委托更新UI(假设在 WinForms 中更新TextBox)this.Invoke(new Action(() =>{textBox.Text += received ;}));
}
6. 多线程处理
推荐使用生产者-消费者模式:
BlockingCollection<string> dataQueue = new BlockingCollection<string>();// 生产者线程
void DataReceivedHandler(...)
{dataQueue.Add(receivedData);
}// 消费者线程
Task.Run(() =>
{foreach (var data in dataQueue.GetConsumingEnumerable()){// 处理数据}
});
五、常见问题与注意事项
1. 注意事项
- 参数一致性:确保双方设备的波特率、数据位、停止位、校验位一致。
- 权限问题:在访问串口时,需要确保程序有相应的权限,否则可能会抛出异常。
- 线程安全:在
DataReceived
事件中处理数据时,由于它是在单独的线程中触发的,若要更新UI控件,必须使用Invoke
方法来确保线程安全 - 异常处理:使用
try-catch
处理Open()
、Read()
、Write()
可能抛出的异常。 - 缓冲区管理:通过
DiscardInBuffer
和DiscardOutBuffer
清空缓冲区,避免数据残留。- 避免重复打开同一端口,关闭前调用
sp.DiscardInBuffer()
清空缓存。
- 避免重复打开同一端口,关闭前调用
- 硬件流控制
在高速传输场景中启用Handshake.RequestToSend
,避免数据丢失。
2. 常见问题
- 端口无法打开
- 检查设备是否占用(如其他程序已连接)
- 确认串口号是否正确(虚拟串口可能动态变化)
- 异常处理:
try...catch(IOException)
捕获端口不存在错误
- 数据接收不完整
- 使用
BytesToRead
确保读取全部缓存数据 - 添加延迟(如
Thread.Sleep(50)
)等待完整帧 - 硬件延迟:部分设备发送数据有间隔,需调整时序
- 使用
- 数据乱码
- 发送/接收端波特率必须一致,否则数据乱码。
- 字符编码问题
- 若接收中文字符乱码,需设置:
serialPort.Encoding = Encoding.GetEncoding("GB2312")
。- 或
serialPort.Encoding = Encoding.UTF8;
六、扩展
1. 跨平台方案(RJCP.SerialPortStream)
对于需要跨平台(Linux/macOS)的场景,推荐使用 RJCP.SerialPortStream 库(通过 NuGet 安装 RJCP.SerialPortStream
):
using RJCP.IO.Ports;SerialPortStream serialPort = new SerialPortStream("COM3");
serialPort.BaudRate = 9600;
serialPort.Open();// 事件处理与读写方式与 SerialPort 类似
serialPort.DataReceived += (sender, e) =>
{byte[] data = new byte[serialPort.BytesToRead];serialPort.Read(data, 0, data.Length);Console.WriteLine(Encoding.UTF8.GetString(data));
};
2. 编码
使用串口通信的时候,会涉及到数据的编码格式,如果我们使用ASCII编码格式,但是接收的时候采用的是其他的编码格式,可能就会导致数据解析错误,因此在一些特定场景下我们需要规定好发送和接收数据的编码格式,这个时候就需要用到System.Text.Encoding
类中的编码解码的功能。
详见:C# System.Text.Encoding 使用详解
3. 清空缓冲区的方法
关于 DiscardInBuffer / DiscardOutBuffer
的使用,详见:C# SerialPort 类中清空缓存区的方法。
4. Handshake 设置
常用握手协议:
Handshake.None
:无握手。Handshake.RequestToSend
:RTS/CTS(请求发送/清除发送)。Handshake.XOnXOff
:软件流控制(XON/XOFF 字符)。
serialPort.Handshake = Handshake.RequestToSend;
详见:C# SerialPort 类中 Handshake 属性的作用
结语
回到目录页:C# 上位机知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。
参考资料:
- 官方文档:SerialPort Class
相关文章:
C# SerialPort 使用详解
总目录 前言 在工业控制、物联网、嵌入式开发等领域,串口通信(Serial Port Communication)是连接串行设备(如条码扫描器、GPS接收器等)与计算机的重要手段。C# 提供了内置的 SerialPort 类,简化了串口开发…...
数据结构--二叉排序树
一、二叉排序树的定义 二叉排序树,又称二叉查找树。 性质: 左子树结点值<根结点值<右子树结点值(进行中序遍历,可以得到一个递增的有序序列) 二、查找操作 利用二叉排序树的性质,如果树空,…...
FPGA的直方图均衡
文章目录 一、直方图均衡二、代码实现三、仿真 一、直方图均衡 直方图均衡(Histogram Equalization)是一种用于增强图像对比度的图像处理技术。它通过重新分配图像像素的灰度值,使得图像的灰度直方图在整个灰度范围内均匀分布,从而…...
使用Python将视频转化为gif
使用Python将视频转化为gif 一、前言二、准备三、测试 一、前言 最近想把喜欢的视频片段作成gif,就试着用Python做了下,感觉效果还行,这里做个记录。 二、准备 先下载安装对应的库,命令如下: pip install moviepy …...
基于javaweb的SpringBoot雪具商城系统设计与实现系统(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、…...
Harbor镜像仓库迁移与高可用集群搭建HTTPS实现实战指南
实验环境 Ubuntu22.04操作系统 registry节点 10.0.0.91 master节点 10.0.0.92 backup节点 10.0.0.93 在企业信息化建设的不同演进阶段,私有镜像仓库的选型策略存在显著差异。近期主导完成某企业级容器镜像仓库升级项目,成功实现Docker Registry至Ha…...
redis--JavaSpring客户端
目录 一、引言 二、配置 三、相关操作 四、总结 一、引言 本篇文章会将redis与spring项目进行结合,看看再spring项目中,redis是如何使用的 二、配置 三、相关操作 四、总结 在spring项目中的使用和在基础项目上的使用有差异,但是差异并不大…...
JavaWeb3
聚合函数:把某一列的数据计算。count,max,min,avg,sum select count(id) from wife;-- 统计个数,不计算null,统计常量表示个数 select count(*) from wife; select min(id) from wife; select avg(age) from wife; 分组查询 select name,c…...
SAP-ABAP:SAP数据集成全场景技术指南(BAPI、RFC、IDOC、BATCHJOB、ODATA、WEBSERVICE):从实时交互到批量处理
SAP数据集成全场景技术指南:从实时交互到批量处理 #mermaid-svg-hpPMerJYUerla0BJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hpPMerJYUerla0BJ .error-icon{fill:#552222;}#mermaid-svg-hpPMerJYUerla0BJ .er…...
QT笔记----QCheckBox
文章目录 概要1、QCheckBox 的基本概念2、单个QCheckBox3、多个QCheckBox同时应用3.1、实现效果3.2、实现Demo 概要 在 Qt 应用程序开发中,QCheckBox 是一个常用的用户界面元素,它允许用户在两种状态(选中和未选中)之间进行切换&a…...
试试智能体工作流,自动化搞定运维故障排查
APO 1.5.0版本全新推出的智能体工作流功能,让运维经验不再零散!只需将日常的运维操作和故障排查经验转化为标准化流程,就能一键复用,效率翻倍,从此告别重复劳动,把时间留给更有价值的创新工作。更贴心的是&…...
3.24[Q]Linux
我正在学习Linux,Linux设备管理是怎样的?详细解释,越细节越好 我正在学习Linux,在Linux设备管理中,什么是char device?以及block,usb device?详细解释,越细节越好 我正在学习Linux࿰…...
深度学习——图像相似度评价指标
这里写目录标题 PSNR(Peak Signal-to-Noise Ratio,峰值信噪比)定义公式代码 SSIMMS-SSIM (Multi Scale Structural Similarity Index Measure,多尺度结构相似性)CSS (Contrast-Structure Similarity 对比结构相似度)MA…...
CentOS安装sshpass工具-自动化SSH密码认证
sshpass是一个在Linux环境下用于自动化SSH密码认证的工具。 一、功能特点 自动化SSH登录:sshpass允许用户在命令行中直接传递密码,从而无需在SSH连接时手动输入密码。这对于自动化脚本和批处理任务非常有用,因为它可以在非交互式环境下完成…...
js 中 如何获取数组的交集【面试题】
一、数组元素为基本类型:Number、String、等基本类型时 1、使用 Set 和 filter(适用于两个数组) const intersection (arr1, arr2) > {const set new Set(arr2);return [...new Set(arr1)].filter(item > set.has(item)); };将第二…...
value-key 的作用
在 el-autocomplete 组件中,value-key 是一个非常重要的属性,它用于指定选项对象中作为值的字段名。当选项列表是一个包含多个属性的对象数组时,value-key 能帮助组件明确哪个属性是实际要使用的值。比如,选项列表为 [{id: 01, na…...
Spring MVC:从历史演变到实战入门
1. Java Web的发展历史与MVC模式 1.1 Model I与Model II的演进 Model I(JSPJavaBean) 作为早期Java Web开发的主流模式,其核心架构如下: graph LR A[客户端] --> B[JSP页面] B --> C{业务逻辑} C --> D[JavaBean] D -…...
Matlab设置表table的表头
用到matlab的table很好用。经常涉及放入数据,读取数据,下面总结常用的知识点。 1. 把不同数据类型放到同一个表中 想把时间类型和数值类型放到统一table中。困扰的点是,我已经知道了表头名称, 如何批量的为表头命名,…...
预测蓝桥杯16届嵌入式省赛客观题
以下是15道蓝桥杯嵌入式省赛客观题预测,每道题均包含**选项列表**、**答案**和**解析**,格式清晰便于快速查阅: 一、预测1 ### **一、STM32G4硬件基础与外设配置** 1. **STM32G431RBT6的Flash和RAM容量分别为?** **选项**&a…...
综合章节:游戏网络化、模组化与深度扩展
模块一:网络功能与玩家数据同步 目标:实现玩家得分上传、全球排行榜展示及云端数据同步。 # network_manager.py(网络请求封装) import requests import threadingclass NetworkManager:def __init__(self, base_url"http:…...
PostgreSQL:索引与查询优化
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
Android Compose 框架的 ViewModel 委托深入剖析(二十)
Android Compose 框架的 ViewModel 委托深入剖析 一、引言 在 Android 开发中,数据的管理和状态的保存是至关重要的。ViewModel 作为 Android 架构组件的一部分,为我们提供了一种在配置更改(如屏幕旋转)时保存数据和管理 UI 状态…...
android|生成二维码qrcode(android)
1.build.gradle implementation com.google.zxing:core:3.4.1引入zxing库 只是生成的话引入core库就可以了 2.封装方法 import android.graphics.Bitmap; import android.graphics.Color;import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; imp…...
element-plus中el-empty空盒子组件和Collapse 折叠面板组件的使用
一.el-empty空盒子组件的使用 直接复制下面的代码: <el-empty description"description" /> 展示效果: 还可以自定义文字描述: <el-empty description"暂未选择患者"/> 二.Collapse 折叠面板组件的使用 复制…...
Windows 和 Linux 操作系统架构对比以及交叉编译
操作系统与架构兼容性详解 1. 可执行文件格式:PE vs ELF Windows: PE (Portable Executable) 格式 详细解释: PE 格式是 Windows 下的可执行文件标准 包含多个区段(Sections),如代码段、数据段、资源段 文件头包含…...
【区块链安全 | 第一篇】密码学原理
文章目录 1.哈希函数1.1 哈希函数的性质1.2 常见哈希算法1.3 Merkle Tree(默克尔树)1.4 HMAC(哈希消息认证码) 2. 公钥密码学2.1 对称加密 vs 非对称加密2.2 RSA 算法2.3 ECC(椭圆曲线密码学)2.4 Diffie-He…...
3.23[A]linux
gedit 是 GNOME 桌面环境下的文本编辑器,类似于 Windows 中的记事本,但功能更强大,支持语法高亮、多文件编辑等特性。它是一个图形化界面的文本编辑器,适合在需要直观编辑文本文件的场景中使用。 gedit 通常用于编辑配置文件、源代…...
AI革命之下的前端将会如何发展?
一、AI 为前端开发带来的变革 (一)提升开发效率 传统的 Web 前端开发常常面临大量重复性工作,如编写简单表单、布局组件等,这些工作耗时费力且易出错,严重影响开发效率和项目进度。而 AI 的出现,通过自动…...
【2025】基于springboot+vue的农产品商城系统设计与实现(源码、万字文档、图文修改、调试答疑)
项目完整功能以演示视频为准 基于Spring Boot Vue的农产品商城系统设计与实现功能结构图如下: 课题背景 随着互联网的普及和电子商务的快速发展,农产品线上销售成为推动农业现代化和乡村振兴的重要力量。传统的农产品销售模式存在信息不对称、销售渠道单…...
沪深300股指期货的看涨看跌方式是怎样的?
沪深300指数代表了中国A股市场中300家大公司的整体表现。股指期货交易允许老板们预测指数未来的涨跌,并从中获利。 沪深300股指期货基础操作 首先,沪深300股指期货中的看涨操作:老板们可以通过买入沪深300股指期货合约,代码也就是…...
使用selenium来获取数据集
使用selenium来获取数据集 1、下载最新的chrome浏览器与chromedriver.exe 查看chrome的版本,打开谷歌浏览器,点击右上角的三个点,然后点击【帮助】, 点击【关于Google Chrome】 然后去下载同样为134版本号的chromedriver.exe, 网址:https://googlechromelabs.github.…...
MCP(大模型上下文协议)
以下是关于大模型MCP协议(Model Context Protocol)的详细介绍,综合其定义、技术架构、应用场景及行业影响: 一、定义与核心目标 **MCP(Model Context Protocol,模型上下文协议)**是由Anthropic…...
FPGA中串行执行方式之流水线(Pipeline)
FPGA中串行执行方式之流水线(Pipeline) 在FPGA设计中,流水线(Pipeline) 是一种常见的优化技术,用于提高系统的吞吐量和性能。流水线通过将复杂的逻辑分解为多个阶段,每个阶段在一个时钟周期内完成一部分工作,并将中间结果传递到下一阶段。这种方式可以显著提高时钟…...
Python 3.8 Requests 爬虫教程(2025最新版)
遵守网站的爬虫规则、避免爬取敏感信息、保护个人隐私! 一、环境配置与基础验证 # 验证 Python 版本(需 ≥3.8) import sys print(sys.version) # 应输出类似 3.8.12 的信息# 安装 requests 库(若未安装) # 命令行执…...
【深度学习】GAN生成对抗网络:原理、应用与发展
GAN生成对抗网络:原理、应用与发展 文章目录 GAN生成对抗网络:原理、应用与发展1. 引言2. GAN的基本原理2.1 核心思想2.2 数学表达2.3 训练过程 3. GAN的主要变体3.1 DCGAN (Deep Convolutional GAN)3.2 CGAN (Conditional GAN)3.3 CycleGAN3.4 StyleGAN…...
LINUX基础 [三] - 进程创建
目录 前言 进程创建的初次了解(创建进程的原理) 什么是fork函数? 初识fork函数 写时拷贝 fork函数存在的意义 fork调用失败的原因 进程终止 运行完毕结果不正确 main函数返回 库函数函数exit 系统调用接口_exit 进程异常终止 进…...
AI比人脑更强,因为被植入思维模型【24】替身决策思维模型
定义 替身决策思维模型是一种在面对复杂问题或决策情境时,通过将自己代入到不同的角色(即“替身”)中,从这些角色的视角出发去思考、分析和做出决策的思维方式。这种思维模型要求决策者暂时摆脱自身固有的思维定式和立场…...
数据清洗:基于python抽取jsonl文件数据字段
基于python抽取目录下所有“jsonl”格式文件。遍历文件内某个字段进行抽取并合并。 import os import json import time from tqdm import tqdm # 需要先安装:pip install tqdmdef process_files():# 设置目录路径dir_path r"D:\daku\关键词识别\1623-00000…...
spring后端处理各种请求
在Spring MVC中处理JSON请求和返回JSON消息的步骤如下: 1. 添加依赖 确保项目中包含处理JSON的库,如Jackson。 Maven配置(pom.xml): <dependency><groupId>com.fasterxml.jackson.core</groupId>…...
企业级部署zabbix分布式监控系统
目录 一、Zabbix分布式监控系统介绍 1.什么是“Zabbix” 2.Zabbix分布式监控系统的特点 3.Zabbix分布式监控系统的原理 4.Zabbix分布式监控系统的运用 5. Zabbix分布式监控系统的部署顺序 二、搭建 1.设备硬件配置参考 2.zabbix分布式监控系统各节点设备名称和IP规划 …...
OkHttp 的证书设置
在 Android 开发中,通过 OkHttp 自定义 SSLSocketFactory 和 X509TrustManager 可以有效增强 HTTPS 通信的安全性,防止中间人攻击(如抓包工具 Charles/Fiddler 的拦截)。以下是实现防抓包的关键技术方案: 一、Okhttp设…...
ETL:数据清洗、规范化和聚合的重要性
在当今这个数据呈爆炸式增长的时代,数据已成为企业最为宝贵的资产之一。然而,数据的海量增长也伴随着诸多问题,如数据来源多样、结构复杂以及质量问题等,这些问题严重阻碍了数据的有效处理与深度分析。在此背景下,ETL&…...
蓝桥杯备考:图的遍历
这道题乍一看好像没什么不对的,但是!但是!结点最大可以到10的5次方!!!我们递归的时间复杂度是很高的,我们正常遍历是肯定通过不了的,不信的话我们试一下 #include <iostream>…...
【多媒体交互】Unity Kinect实现UI控件的点击
在Unity中,通过Kinect实现UI控件的点击功能,主要涉及手部追踪、坐标映射和手势检测三个核心环节。 实现步骤 初始化Kinect与关节追踪 使用KinectManager获取用户ID和手部关节点(如JointType.HandLeft)的坐标。 long userId _…...
QinQ项展 VLAN 空间
随着以太网技术在网络中的大量部署,利用 VLAN 对用户进行隔离和标识受到很大限制。因为 IEEE802.1Q 中定义的 VLAN Tag 域只有 12 个比特,仅能表示 4096 个 VLAN,无法满足城域以太网中标识大量用户的需求,于是 QinQ 技术应运而生。…...
OBS虚拟背景深度解析:无需绿幕也能打造专业教学视频(附插件对比)
想要录制教学视频却苦于背景杂乱?本文将手把手教你用OBS实现专业级虚拟背景效果,无需绿幕也能轻松营造沉浸式教学场景。文末附6个提升画面质感的免费背景资源! 一、虚拟背景的核心价值:从「教师宿舍」到「虚拟讲堂」的蜕变 我们调…...
26考研——图(6)
408答疑 文章目录 一、图的基本概念二、图的存储三、图的遍历四、图的应用五、图的代码实操六、参考资料鲍鱼科技课件26王道考研书 七、总结图的存储结构邻接矩阵邻接表 图的遍历图的相关概念完全图和连通图图的连通性 关键路径学习建议 一、图的基本概念 文章链接: link 二、…...
Redis常用数据类型深度解析:从理论到最佳实践
Redis常用数据类型深度解析:从理论到最佳实践 一、引言二、Redis数据类型全景图三、核心数据类型详解**1. String(字符串)****2. Hash(哈希表)****3. List(列表)****4. Set(集合&…...
DeepSeek-V3 模型更新,加量不加价
DeepSeek V3-0324 是 DeepSeek V3 系列的重要升级版本,虽然被官方称为「小版本迭代」,但其在技术能力、开源策略和用户体验上均有显著提升。以下是主要新特性功能和核心变化: 推理能力 基准测试性能显著提升: MMLU-Pro࿱…...
Vue项目的 Sass 全局基础样式格式化方案,包含常见元素的样式重置
步骤 1:创建全局样式文件 在项目中创建文件:src/assets/scss/global.scss 内容如下: // 全局盒模型设定(边框计入宽高) *, *::before, *::after {box-sizing: border-box;margin: 0;padding: 0; }// 基础元素样式重置…...