一个提取DXF文件 获取图纸信息的半成品~求大佬优化~
By
☜李長新☞
at 2022-03-03 • 0人收藏 • 927人看过
原理:dxf是文本方式保存dwg图纸的信息,提取包含关键字的行 这样就知道这个CAD图纸里面有哪些需要的资料了。
问题:代码执行分析效率低,速度慢,还会爆内存不足。
同原理的PowerShell代码效率要快的多。
PowerShell文件放在DXF文件的同文件夹内使用,代码如下:
$start = Get-Date #记录脚本开始执行时间 ForEach( $file In (dir "*.dxf") ) { #这里加了双引号,不加双引号的时候会出现找不到路径报错 $arr = [IO.File]::ReadAllLines($file, [Text.Encoding]::Default); $arr = $arr -match '工程|工图|板图|由图|配图|序图|统图|面图|意图|程图|盘图|布图|998KAS|998SLX|998SFX|998YJS|998JSX|998YPH|998TGX|998BCX|998TMS|998MGT|998SCX|998ZPX|998YCX|998KYB' -replace '\s+'; #匹配包含"工程" 或 "图"的行、删除空格 $arr = $arr -replace '^\(\(FRAME.*PLOTFILEPREFIX."([^"]+)".*$', '$1'; #提取:“((FRAME .”开头的行中(PLOTFILEPREFIX . "******(工程名称)******_")这一段""双引号内的内容其余部分删除 $arr = $arr -NotMatch '^.{1,5}$|数据链接\^|[c-zC-Z]:\\|"TCH_KERNAL|在选择|说明|关闭|宋体|施工测量|单接杆|本工程' #删除不符合要求的行 $arr = $arr | sort -Unique; #删除重复行 $str += '"' + $file.Name + '","' + ($arr -join '","') + '"' + "`r`n"; } #Get-ChildItem variable: #显示出变量的值以便查看问题出现在哪里 sc DXF图纸信息.CSV -Value $str; $end = Get-Date #记录脚本结束执行时间 Write-Host -ForegroundColor Red ('Total Runtime: ' + ($end - $start).TotalSeconds) #显示脚本执行时间
Aardio代码如下:
import win.ui; io.open(); /*DSG{{*/ mainForm = win.form(text="DWG关键字信息提取";right=405;bottom=542) mainForm.add( AddDxfMenu={cls="button";text="选择图纸文件夹";left=153;top=163;right=267;bottom=187;z=10}; AddKeyWord={cls="button";text="添加";left=153;top=72;right=220;bottom=96;z=5}; DelKeyWord={cls="button";text="删除";left=236;top=72;right=303;bottom=96;z=6}; DxfMenu={cls="edit";text="F:\天翼云下载\验收图纸\DXF";left=152;top=132;right=385;bottom=156;edge=1;z=9}; FileLocation={cls="edit";left=153;top=196;right=386;bottom=220;edge=1;z=11}; KeyWord={cls="edit";text="请输入...";left=153;top=39;right=386;bottom=63;edge=1;z=4}; KeyWordlist={cls="listbox";left=14;top=40;right=128;bottom=534;acceptfiles=1;edge=1;items={};vscroll=1;z=2}; LogPrint={cls="edit";left=153;top=287;right=386;bottom=485;autohscroll=false;edge=1;multiline=1;vscroll=1;z=14}; NulKeyWord={cls="button";text="清空";left=319;top=72;right=386;bottom=96;z=7}; SetFileLocation={cls="button";text="设置保存位置";left=272;top=163;right=386;bottom=187;z=12}; StarBut={cls="button";text="开始";left=145;top=237;right=263;bottom=263;z=15}; StopBut={cls="button";text="停止";left=276;top=236;right=394;bottom=262;z=16}; groupKey={cls="groupbox";text="关键字管理";left=145;top=19;right=394;bottom=110;edge=1;z=3}; groupLog={cls="groupbox";text="输出日志";left=145;top=266;right=394;bottom=534;edge=1;z=13}; groupOS={cls="groupbox";text="读取/保存";left=145;top=111;right=394;bottom=230;edge=1;z=8}; progress={cls="progress";left=153;top=508;right=386;bottom=527;edge=1;max=100;min=0;z=17}; static={cls="static";text="关键字列表:";left=21;top=15;right=108;bottom=36;align="center";center=1;transparent=1;z=1}; static2={cls="static";text="清单读取/处理进度:";left=153;top=487;right=386;bottom=507;center=1;transparent=1;z=18} ) /*}}*/ //关键字列表默认设置 list = {"工程";"工图";"板图";"由图";"配图";"序图";"统图";"面图";"意图";"程图";"盘图";"布图";"998KAS";"998SLX";"998SFX";"998YJS";"998JSX";"998YPH";"998TGX";"998BCX";"998TMS";"998MGT";"998SCX";"998ZPX";"998YCX";"998KYB"}; 关键字匹配规则 = '<'++string.join( list, '>|<' )++'>' io.print("关键字匹配规则:",关键字匹配规则) list = table.unique(list); for(v,k in list ){ mainForm.KeyWordlist.add(k); } //添加关键字列表KeyWordlist mainForm.AddKeyWord.oncommand = function(id,event){ str = mainForm.KeyWord.text; mainForm.KeyWordlist.add(str) mainForm.KeyWordlist.selIndex = mainForm.KeyWordlist.count; mainForm.KeyWordlist.items = table.unique(mainForm.KeyWordlist.items); 关键字匹配规则 = '<'++string.join( mainForm.KeyWordlist.items, '>|<' )++'>' mainForm.LogPrint.text = "" mainForm.LogPrint.log( 关键字匹配规则,'\r\n' ) //io.print(关键字匹配规则); } //清空关键字列表KeyWordlist mainForm.NulKeyWord.oncommand = function(id,event){ mainForm.KeyWordlist.clear(); mainForm.redraw(); mainForm.LogPrint.log( 关键字匹配规则,'\r\n' ) } //删除关键字 mainForm.DelKeyWord.oncommand = function(id,event){ mainForm.KeyWordlist.delete(); 关键字匹配规则 = '<'++string.join( mainForm.KeyWordlist.items, '>|<' )++'>' mainForm.LogPrint.text = "" mainForm.LogPrint.log( 关键字匹配规则,'\r\n' ) //io.print(关键字匹配规则); } //选择图纸文件夹DxfMenu import fsys.dlg; mainForm.AddDxfMenu.oncommand = function(id,event){ Dxfmenu = fsys.dlg.opendir(); mainForm.DxfMenu.text = Dxfmenu } //设置保存文件地址FileLocation mainForm.SetFileLocation.oncommand = function(id,event){ Filemenu = fsys.dlg.opendir(); mainForm.FileLocation.text = Filemenu } var 开始处理 = function(mainForm){ import time.performance; import console; var tk = time.performance.tick(); //mainForm.LogPrint.print("开始处理") //遍历目录 import fsys; //循环目录获取文件列表filelist filelist = {}; mainForm.LogPrint.print("开始处理路径:",mainForm.DxfMenu.text); fsys.enum(mainForm.DxfMenu.text, //指定要遍历的目录 "*.dxf", //指定查询文件名,支持windows掩码 function(dir,filename,fullpath,findData){ //io.print(dir,filename,fullpath,findData) //import console; //console.varDump(findData) if(filename){ //io.print("发现文件:",filename) //io.print("文件路径:",fullpath) //将文路径添加至文件列表 table.push(filelist,fullpath); } else{ io.print("发现目录:",dir) } //return false; } //function结束。 )//遍历结束。 关键字匹配规则 = '<'++string.join( mainForm.KeyWordlist.items, '>|<' )++'>' var 用时 = ( time.performance.tick() - tk ) / 1000 mainForm.LogPrint.print("读取到"++#filelist++"个文件。用时:"++用时++"秒"); mainForm.static2.text = "清单读取/处理进度:"++#filelist++"/0" //初始化进度条 mainForm.progress.min = 0; mainForm.progress.max = #filelist; mainForm.progress.pos = 0; mainForm.progress.hide = false; //显示进度条 for(k,filename in filelist){ //循环读取文件列表 tk2 = time.performance.tick(); var ss = {}; mainForm.LogPrint.print("开始处理"++filename); var str = string.load(filename) var list = string.splitEx(str); var newTab = table.unique(list); for(i=1;#newTab;1){ s = string.match(string.fromto(newTab[i],936,65001),关键字匹配规则) if(s!=null){ table.push(ss,newTab[i]) } } newTab = table.unique(ss); if(mainForm.FileLocation.text!=null){ 保存地址 = mainForm.FileLocation.text++"\识别结果.csv" }else { 保存地址 = "C:\Users\Lcx\Desktop\识别结果.csv" } filename =string.fromto(filename,65001,936) file = io.open (保存地址,"a+" ) file.write(filename++","++string.fromto(string.join(newTab,","),65001,936)++'\n'); file.close(); var 用时2 = ( time.performance.tick() - tk2 ) / 1000 mainForm.LogPrint.print(file,"处理完成,用时:"++用时2++"秒") mainForm.progress.stepIt(); mainForm.static2.text = "清单读取/处理进度:"++#filelist++"/"++k } 用时 = ( time.performance.tick() - tk ) / 1000 mainForm.LogPrint.print("识别结果保存至:",保存地址++"总计用时:"++用时++"秒") mainForm.StarBut.disabled = false; } mainForm.StarBut.oncommand = function(id,event){ hander,id_t = thread.create( 开始处理,mainForm); mainForm.LogPrint.print(hander,id_t) mainForm.StarBut.disabled = true; } mainForm.StopBut.oncommand = function(id,event){ ::PostThreadMessage(id_t,0x12/*_WM_QUIT*/,0,0) thread.waitAll(hander); thread.set("红灯停", false) raw.closehandle(hander) io.print("线程已退出") mainForm.StarBut.disabled = false; } mainForm.FileLocation.oncommand = function(id,event){ } mainForm.show(); return win.loopMessage();
4 个回复 | 最后更新于 2022-02-28
回复#1 @jacen : 文件附件已上传,测试后时间对比如下图。
附件:附件下载
修改后的处理时间还是比较长修改后如下:
var 优化处理 = function(mainForm){ //线程内引入扩展库 import time.performance; import console; import fsys; //开始计时 var tk = time.performance.tick(); mainForm.LogPrint.print("开始处理:",mainForm.DxfMenu.text); //设置匹配关键字 关键字匹配规则 = '<'++string.join( mainForm.KeyWordlist.items, '>|<' )++'>' //循环读取文件夹 fsys.enum(mainForm.DxfMenu.text, "*.dxf", function(dirname,filename,fullpath,findData){ //如果读取到DXF文件 if(filename){ var ss = {};//符合条件的文字列表 mainForm.LogPrint.print("开始处理:",filename); //开始单文件处理计时 tk2 = time.performance.tick(); for line in io.lines(fullpath) { if( string.find(line,关键字匹配规则) ){ //将符合条件的行加入SS列表 table.push(ss,line) } } //去重 newTab = table.unique(ss); //保存单文件处理结果 if(mainForm.FileLocation.text!=null){ 保存地址 = mainForm.FileLocation.text++"\识别结果.csv" }else { 保存地址 = "D:\识别结果.csv" } file = io.open (保存地址,"a+" ) file.write(string.fromto(filename,65001,936) ++","++string.fromto(string.join(newTab,","),65001,936)++'\n'); file.close(); } //计算单文件处理完成用时 var 用时2 = ( time.performance.tick() - tk2 ) / 1000 mainForm.LogPrint.print(filename,"处理完成,用时:"++用时2++"秒") } ); //计算总用时 用时 = ( time.performance.tick() - tk ) / 1000 mainForm.LogPrint.print("识别结果保存至:",保存地址++"总计用时:"++用时++"秒") mainForm.StarBut.disabled = false; }
登录后方可回帖
我觉得file的io操作,是不是要写道循环外面, 就类似sqlite批量写入要用事件, 如果文件多了, 效率改善就体现出来了, 另外你这一次把整个文件读出来进行处理, 如果文件大了,内存需求也大,读取时间也久, 用每行处理应该会快很多
ps:我试了下, 感觉效率还可以啊,是我文件太少太小了吗