在判断头帧以后 下位机发过的数据 偶尔会发过来9个字节的数据 如果我按照10个字节的数据进行截取 后面就截取不到对的数据,我该如何把中间9个字节的数据 筛选掉 只要10个字节的数据 如果有思路请直接贴代码并注释上 注释,如果按照需求可以正常运行 我会采纳
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// 检查是否允许跨线程调用控件,这里为了简化代码直接禁用了该功能
CheckForIllegalCrossThreadCalls = false;
// 读取所有可用字节数
int bytesToRead = serialPort1.BytesToRead;
//用于存储接收到的数据
byte[] receiveBuffer = new byte[bytesToRead];
//从串口读取数据
serialPort1.Read(receiveBuffer, 0, bytesToRead);
buffer.AddRange(receiveBuffer);
//将接收到的数据转换为字符串格式
if (buffer.Count >0 && buffer[0] == 0x68)
{
//如果缓冲区的长度大于等于8,则表示已经接收到完整的数据帧
if (buffer.Count >= 10)
{ //截取需要的10个字节数据
byte[] data = buffer.GetRange(0,10).ToArray();
//将接收到的数据转换为字符串格式
receivedString = BitConverter.ToString(data).Replace("-", "");
textBox1.AppendText(receivedString);
//将字符串追加至文本框中
string timeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
using (StreamWriter sw = new StreamWriter(@"C:\Users\guoxiaoru\Desktop\ACVB.txt", true))
{
sw.WriteLine(timeStr + " " + receivedString, "\n");
sw.Close();
}
//清空缓冲区
buffer.Clear();
}
}
//清空缓冲区
else { buffer.Clear(); }
}
参考gpt和自己的思路,在判断头帧以后,可以先判断缓冲区的长度是否为9,如果是,则将缓冲区清空;如果不是,则按照10个字节的数据进行截取。可以参考如下代码:
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// 检查是否允许跨线程调用控件,这里为了简化代码直接禁用了该功能
CheckForIllegalCrossThreadCalls = false;
// 读取所有可用字节数
int bytesToRead = serialPort1.BytesToRead;
//用于存储接收到的数据
byte[] receiveBuffer = new byte[bytesToRead];
//从串口读取数据
serialPort1.Read(receiveBuffer, 0, bytesToRead);
buffer.AddRange(receiveBuffer);
//将接收到的数据转换为字符串格式
if (buffer.Count > 0 && buffer[0] == 0x68)
{
//如果缓冲区的长度等于9,则表示中间有9个字节的无用数据
if (buffer.Count == 9)
{
//清空缓冲区
buffer.Clear();
}
//如果缓冲区的长度大于等于10,则表示已经接收到完整的数据帧
else if (buffer.Count >= 10)
{ //截取需要的10个字节数据
byte[] data = buffer.GetRange(0,10).ToArray();
//将接收到的数据转换为字符串格式
receivedString = BitConverter.ToString(data).Replace("-", "");
textBox1.AppendText(receivedString);
//将字符串追加至文本框中
string timeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
using (StreamWriter sw = new StreamWriter(@"C:\Users\guoxiaoru\Desktop\ACVB.txt", true))
{
sw.WriteLine(timeStr + " " + receivedString, "\n");
sw.Close();
}
//清空缓冲区
buffer.Clear();
}
}
//清空缓冲区
else { buffer.Clear(); }
}
参考GPT和自己的思路,首先,你需要判断接收到的数据是否满足你的要求,即长度是否为10个字节。如果不满足,你可以忽略这些数据。这可以使用以下代码来实现:
if (data.Length != 10) {
// 数据长度不为10,忽略此数据
return;
}
// 数据长度为10,进行后续处理
// TODO: 处理数据
如果你需要在数据中截取特定的位置,你可以使用 Array.Copy() 方法。以下是一个例子,它从数组 data 的第二个字节开始复制八个字节,并将结果存储在 buffer 数组中:
byte[] buffer = new byte[8];
Array.Copy(data, 1, buffer, 0, 8);
在这个例子中,data 是接收到的数据数组,1 是要开始复制的索引位置,buffer 是用来存储结果的数组,0 是存储结果的数组中的起始索引位置,8 是要复制的字节数。你可以根据你的需要调整这些值。
如果你需要在每个数据帧中跳过中间的9个字节,你可以使用一个循环来接收数据,并检查每个数据帧的长度。以下是一个示例代码:
while (true) {
// 接收数据帧
byte[] data = ReceiveData();
// 检查数据帧长度
if (data.Length != 10) {
// 数据长度不为10,忽略此数据
continue;
}
// 处理数据帧
// TODO: 处理数据帧
}
在这个例子中,ReceiveData() 方法用来接收数据帧。如果数据帧长度不为10,则跳过此数据帧并继续等待下一个数据帧。如果数据帧长度为10,则进行处理。你可以根据你的需要进行调整。
该回答引用ChatGPT
这里介绍LINQ+Lambda表达式进行数据筛选的方式
这里是第一种方式,还是使用了if条件语句去判断,根据选择的条件去筛选出我所需要的数据
public GxAnaly SelectDay(string ID, DateTime Day)
{
try
{
DBEntities db = new DBEntities();
var temp = (from pt in db.Tb_Analysis
where pt.ID == Sn
select pt).ToList();
// return temp.Any() ? LoadFromModel(temp.First()) : null;
if (temp.Count == )
{
return null;
}
else
{
List<Analy> gxDetail = new List<Analy>();
List<Analy> Detail = new List<Analy>();
temp.ForEach(e => gxDetail.Add(LoadFromModel(e)));
foreach (Analy Detail in gxDetail)
{
if (Detail.OtTime.Day == Day.Day&&Detail.OtTime.Month==Day.Month&&Detail.OtTime.Year==Day.Year)
{
Detail.Add(Detail);
}
}
if (Detail.Count == )
{
return null;
}
else
{
return Detail.FirstOrDefault();
}
}
}
catch (Exception ex)
{
return null;
Logger.Error(ex.Message + ex.StackTrace);
}
}
第二种方式,直接用Lambda自带的筛选属性
using(var db=new MyDbContext())
{
var s= db.Students.ToList().First(s=>s.ID=);
}
//这里写的是进行全表查询,不建议使用
//根据相应的条件进行查询,不会去查询全表,特别在数据量庞大的时候,建议加个判断
using(var db=new MyDbContext())
{
var list =db.Students.AsQueryable();
if(********){list=list.Where(s=>s.ID=);}
if(******){list=list.Where(...)}
}
下面展示一个多个Lambda表达式进行表操作的方法
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
{
// build parameter map (from parameters of second to parameters of first)
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
// replace parameters in the second lambda expression with parameters from the first
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
// apply composition of lambda expression bodies to parameters from the first expression
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.And);
}
完美的动态拼接Lambda表达式如下:
using (var db = new MyDbContext())
{
var predicate = PredicateBuilder.True<Student>();
predicate=predicate.And(s => s.ID > );
predicate=predicate.Or(s => s.ID < );
var result = db.Students.Where(predicate).ToList();
}
下面是一种多Lambda表达式操作的一个范例,这里部分引用来自https://blog.csdn.net/leewhoee/article/details/8968023%EF%BC%8C%E8%87%AA%E5%B7%B1%E6%87%92%E5%BE%97%E5%8E%BB%E6%95%B2%E4%BA%86%EF%BC%8C%E9%A1%BA%E6%89%8B%E5%B0%B1%E5%80%9F%E6%9D%A5%E7%94%A8%E4%BA%86
using (var db = new SHTrackerDbContext())
{
var predicate = PredicateBuilder.True<Course>();
settings = DecorateSettings(settings);
Expression<Func<Course, bool>> checkCourse = c => db.Students.Any(s => s.CourseID == c.ID);
if (!string.IsNullOrEmpty(settings.Quater_Year))
{
checkCourse =
c => db.Students.Any(s => s.CourseID == c.ID && db.Student2CBOs.Any(
s2c => s2c.StudentID == s.ID && s2c.Quater_Year.Equals(settings.Quater_Year)));
}
if (settings.QuaterYearArray != null)
{
checkCourse =
c => db.Students.Any(s => s.CourseID == c.ID && db.Student2CBOs.Any(
s2c =>
s2c.StudentID == s.ID && settings.QuaterYearArray.Any(qy => qy.Equals(s2c.Quater_Year))));
}
if (!string.IsNullOrEmpty(settings.DPU_ID))
{
checkCourse =
checkCourse.And(
c => db.Students.Any(s => s.CourseID == c.ID && s.DPU_ID.Equals(settings.DPU_ID)));
}
predicate = predicate.And(checkCourse);
if (settings.IsCheckInstructorName)
{
predicate = predicate.And(c => c.InstructorName.Equals(settings.InstructorName));
}
if (!string.IsNullOrEmpty(settings.Term))
{
predicate = predicate.And(c => c.TermDescription.Equals(settings.Term));
}
if (settings.TermArray != null)
{
predicate = predicate.And(c => settings.TermArray.Any(t => t.Equals(c.TermDescription)));
}
if (settings.CourseType != CourseType.All)
{
predicate = predicate.And(c => c.Type == (int) settings.CourseType);
}
var cc =
new CourseCollection(
db.Courses.AsNoTracking()
.Where(predicate)
.OrderByDescending(m => m.ID)
.Skip((pageIndex - )*pageSize)
.Take(pageSize)
.ToList(),
db.Courses.AsNoTracking().Where(predicate).Count())
{
PageIndex = pageIndex,
PageSize = pageSize,
Settings = DecorateSettings(settings)
};
return cc;
}
这个用linq中对数组进行 skip 和 take 操作,再 ToArray()
哥哥在你的代码中,当接收到数据后,你首先检查了数据帧头是否正确,然后判断缓冲区中接收到的数据长度是否大于等于10。如果是这种情况,你就从缓冲区中提取十个字节的数据,并将其转换为字符串格式。如果缓冲区中接收到的数据长度小于10,则不进行任何处理并清空缓冲区。
现在假设你想要过滤掉那些长度为9字节的数据,并且只处理长度为10字节的数据。可以在读取完整个缓冲区之前,对缓冲区中的数据进行分析,然后只提取长度为10字节的数据。
以下是修改后的代码示例:
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// 检查是否允许跨线程调用控件,这里为了简化代码直接禁用了该功能
CheckForIllegalCrossThreadCalls = false;
// 读取所有可用字节数
int bytesToRead = serialPort1.BytesToRead;
//用于存储接收到的数据
byte[] receiveBuffer = new byte[bytesToRead];
//从串口读取数据
serialPort1.Read(receiveBuffer, 0, bytesToRead);
buffer.AddRange(receiveBuffer);
// 如果缓冲区的长度小于10,则等待下一个数据包
if (buffer.Count < 10) return;
// 找到数据包的起始位置
int startIndex = buffer.IndexOf(0x68);
// 如果在缓冲区中没有找到数据包起始位置,则清空缓冲区
if (startIndex == -1)
{
buffer.Clear();
return;
}
// 如果数据包起始位置不在缓冲区的开头,则删除该起始位置之前的所有数据
if (startIndex != 0)
{
buffer.RemoveRange(0, startIndex);
}
// 如果缓冲区的长度小于10,则等待下一个数据包
if (buffer.Count < 10) return;
// 如果已经接收到完整的数据包,则提取该数据包并处理
byte[] data = buffer.GetRange(0, 10).ToArray();
// 检查数据包长度是否为10,如果不是,则清除数据包并等待下一个数据包
if (data.Length != 10)
{
buffer.Clear();
return;
}
// 将接收到的数据转换为字符串格式
receivedString = BitConverter.ToString(data).Replace("-", "");
textBox1.AppendText(receivedString);
//将字符串追加至文本框中
string timeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
using (StreamWriter sw = new StreamWriter(@"C:\Users\guoxiaoru\Desktop\ACVB.txt", true))
{
sw.WriteLine(timeStr + " " + receivedString, "\n");
sw.Close();
}
// 清空缓冲区
buffer.Clear();
}
这个代码做了以下这几个事:
哥哥请看看
可以使用一个循环,每次读取10个字节,如果读取到9个字节就再读取一次,直到读取到10个字节为止。
示例代码:
data = b'' # 存储接收到的数据
while True:
# 读取10个字节
chunk = ser.read(10)
# 如果读取到9个字节
if len(chunk) == 9:
# 再读取一次
chunk += ser.read(1)
# 如果读取到10个字节
if len(chunk) == 10:
data += chunk
# 处理数据
process_data(data)
# 清空数据
data = b''
在这个示例代码中,ser
是一个串口对象,process_data()
是处理数据的函数。每次读取到10个字节的数据后,将数据添加到 data
变量中,并调用 process_data()
函数处理数据。处理完数据后,清空 data
变量,等待下一次读取数据。如果读取到9个字节的数据,就再读取一次,直到读取到10个字节为止。
你这一点一点的问,真不如找个人直接远程把你的需求问清楚了,一块弄出来