C#提取文件時(shí)間戳實(shí)現(xiàn)實(shí)現(xiàn)與性能優(yōu)化
在汽車電子和工業(yè)控制領(lǐng)域,CAN總線是最常用的通信協(xié)議之一。而ASC(ASCII)文件作為CAN總線數(shù)據(jù)的標(biāo)準(zhǔn)日志格式,廣泛應(yīng)用于數(shù)據(jù)記錄和分析場(chǎng)景。本文將深入探討如何高效地從CAN ASC文件中提取時(shí)間戳數(shù)據(jù),并分享一個(gè)高性能的C#實(shí)現(xiàn)方案。
一、CAN ASC文件格式解析
CAN ASC文件是一種基于文本的日志格式,通常包含CAN總線的通信時(shí)間戳、消息ID、數(shù)據(jù)長(zhǎng)度和數(shù)據(jù)內(nèi)容。一個(gè)典型的ASC文件片段如下:
date Tue Aug 22 15:35:42 2023
base hex timestamps absolute
0.000000 18F00000x Rx d 8 00 00 00 00 00 00 00 00 Channel=1
0.001000 18F00001x Rx d 8 00 00 00 00 00 00 00 00 Channel=1
0.002000 18F00002x Rx d 8 00 00 00 00 00 00 00 00 Channel=1
其中,每行的第一個(gè)字段(如0.000000)即為時(shí)間戳,表示消息發(fā)送的相對(duì)或絕對(duì)時(shí)間。在解析時(shí),我們需要跳過(guò)文件頭的元數(shù)據(jù)行,從第三行開(kāi)始提取時(shí)間戳信息。
二、時(shí)間戳提取的C#實(shí)現(xiàn)
下面是一個(gè)高效的C#實(shí)現(xiàn),用于從ASC文件中提取時(shí)間戳數(shù)據(jù):
public class AscExtractor { public List<decimal> Extract(string path) { var text = ""; using (var sr = new StreamReader(path)) { text = sr.ReadToEnd(); } var options = StringSplitOptions.RemoveEmptyEntries; return text.Split(new char[] { '\n', '\r' }, options) .Where(t => !string.IsNullOrWhiteSpace(t)) .Skip(2) .Select(t => t.Split(new char[] { ' ', '\t' }, options)) .Select(t => t[0]) .Select(t => decimal.Parse(t)) .ToList(); } }
代碼解析:
- 文件讀?。菏褂肧treamReader一次性讀取整個(gè)文件內(nèi)容,適用于中等大小的ASC文件。
- 行分割:通過(guò)Split方法將文本按行分割,并移除空行。
- 跳過(guò)頭部:使用Skip(2)跳過(guò)文件的前兩行元數(shù)據(jù),可根據(jù)實(shí)際情況調(diào)整。
- 字段提取:對(duì)每行數(shù)據(jù)按空格或制表符分割,提取第一個(gè)字段作為時(shí)間戳。
- 類型轉(zhuǎn)換:將字符串類型的時(shí)間戳解析為decimal類型,確保高精度。
三、性能優(yōu)化與最佳實(shí)踐
1. 大文件處理優(yōu)化
對(duì)于GB級(jí)別的超大ASC文件,一次性讀取整個(gè)文件會(huì)導(dǎo)致內(nèi)存溢出??刹捎昧魇教幚矸绞剑?/p>
public List<decimal> ExtractLargeFile(string path) { var timestamps = new List<decimal>(); using (var sr = new StreamReader(path)) { // 跳過(guò)頭部 sr.ReadLine(); sr.ReadLine(); var line = ""; while ((line = sr.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line)) { continue; } var fields = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (fields.Length > 0) { timestamps.Add(decimal.Parse(fields[0])); } } } return timestamps; }
2. 異常處理增強(qiáng)
在實(shí)際應(yīng)用中,ASC文件可能包含格式錯(cuò)誤的行,需要添加異常處理:
public List<decimal> ExtractWithErrorHandling(string path) { var timestamps = new List<decimal>(); using (var sr = new StreamReader(path)) { // 跳過(guò)頭部 sr.ReadLine(); sr.ReadLine(); var line = ""; var lineNumber = 3; // 從第三行開(kāi)始計(jì)數(shù) while ((line = sr.ReadLine()) != null) { try { if (string.IsNullOrWhiteSpace(line)) continue; var fields = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (fields.Length > 0) { timestamps.Add(decimal.Parse(fields[0])); } } catch (Exception ex) { // 記錄錯(cuò)誤行號(hào)和錯(cuò)誤信息 Console.WriteLine($"Error parsing line {lineNumber}: {ex.Message}"); } lineNumber++; } } return timestamps; }
3. 并行處理加速
對(duì)于多核CPU系統(tǒng),可使用PLINQ并行處理提高解析速度:
public List<decimal> ExtractParallel(string path) { string text; using (var sr = new StreamReader(path)) { text = sr.ReadToEnd(); } return text.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries) .AsParallel() .AsOrdered() .Where(line => !string.IsNullOrWhiteSpace(line)) .Skip(2) .Select(line => { var fields = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); return decimal.Parse(fields[0]); }) .ToList(); }
四、應(yīng)用場(chǎng)景與擴(kuò)展
1. 時(shí)間序列分析
提取的時(shí)間戳可用于分析CAN消息的發(fā)送頻率、間隔分布等時(shí)序特征,幫助診斷總線負(fù)載和通信異常。
2. 數(shù)據(jù)可視化
結(jié)合圖表庫(kù)(如OxyPlot、Chart.js),將時(shí)間戳與CAN消息內(nèi)容結(jié)合,直觀展示總線通信狀態(tài):
3. 高性能擴(kuò)展
對(duì)于工業(yè)級(jí)應(yīng)用,可考慮使用MemoryMappedFile進(jìn)行內(nèi)存映射讀取,或使用Span<T>進(jìn)行零分配解析,進(jìn)一步提升性能。
五、總結(jié)
本文介紹了CAN ASC文件的格式特點(diǎn),并提供了多種C#實(shí)現(xiàn)方案來(lái)提取時(shí)間戳數(shù)據(jù)。在實(shí)際應(yīng)用中,應(yīng)根據(jù)文件大小、性能需求和容錯(cuò)要求選擇合適的實(shí)現(xiàn)方式。對(duì)于中小文件,可使用簡(jiǎn)潔的LINQ鏈?zhǔn)教幚恚粚?duì)于大文件,則建議采用流式處理或并行解析。通過(guò)合理優(yōu)化,可實(shí)現(xiàn)每秒百萬(wàn)級(jí)時(shí)間戳的高效提取,滿足大多數(shù)工業(yè)和汽車電子領(lǐng)域的數(shù)據(jù)分析需求。
到此這篇關(guān)于C#提取文件時(shí)間戳實(shí)現(xiàn)實(shí)現(xiàn)與性能優(yōu)化的文章就介紹到這了,更多相關(guān)C#提取文件時(shí)間戳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#調(diào)用Windows的API實(shí)現(xiàn)窗體動(dòng)畫
在VF、VB、PB的應(yīng)用中,有些無(wú)法通過(guò)語(yǔ)言工具本身來(lái)完成的或者做得不理想的功能,我們會(huì)考慮通過(guò)Windows的API來(lái)完成。本文就來(lái)通過(guò)調(diào)用Windows的API實(shí)現(xiàn)窗體動(dòng)畫,感興趣的可以嘗試一下2022-11-11WPF利用RichTextBox實(shí)現(xiàn)富文本編輯器
在實(shí)際應(yīng)用中,富文本隨處可見(jiàn),那么在WPF開(kāi)發(fā)中,如何實(shí)現(xiàn)富文本編輯呢?本文以一個(gè)簡(jiǎn)單的小例子,簡(jiǎn)述如何通過(guò)RichTextBox實(shí)現(xiàn)富文本編輯功能,需要的可以參考下2024-02-02如何在C# 中查找或結(jié)束程序域中的主、子進(jìn)程
這篇文章主要介紹了如何在C# 中查找或結(jié)束程序域中的主、子進(jìn)程,幫助大家更好的理解和使用c#編程語(yǔ)言,感興趣的朋友可以了解下2020-11-11C#?wpf使用DockPanel實(shí)現(xiàn)制作截屏框
做桌面客戶端的時(shí)候有時(shí)需要實(shí)現(xiàn)截屏功能,能夠在界面上框選截屏,本文就來(lái)為大家介紹一下wpf如何使用DockPanel制作截屏框吧,感興趣的可以了解下2023-09-09C#制作多線程處理強(qiáng)化版網(wǎng)絡(luò)爬蟲(chóng)
這篇文章主要介紹了C#制作多線程處理強(qiáng)化版網(wǎng)絡(luò)爬蟲(chóng)的相關(guān)代碼,有想學(xué)習(xí)C#多線程編程的小伙伴可以參考下2016-09-09C#實(shí)現(xiàn)Dictionary字典賦值的方法
本文主要介紹了C#實(shí)現(xiàn)Dictionary字典賦值的方法,如同java中的Hasttable,C#里面有Dictionary,可以實(shí)現(xiàn)很高效的鍵值對(duì)操作。感興趣的可以了解一下2021-05-05Quartz.Net實(shí)現(xiàn)原理及使用方法詳解
這篇文章主要介紹了Quartz.Net實(shí)現(xiàn)原理及使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12