一个提取DXF文件 获取图纸信息的半成品~求大佬优化~

By ☜李長新☞ at 2022-03-03 • 0人收藏 • 381人看过

原理: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
2022-03-04   #1

我觉得file的io操作,是不是要写道循环外面, 就类似sqlite批量写入要用事件, 如果文件多了, 效率改善就体现出来了, 另外你这一次把整个文件读出来进行处理, 如果文件大了,内存需求也大,读取时间也久, 用每行处理应该会快很多

ps:我试了下, 感觉效率还可以啊,是我文件太少太小了吗

2022-03-04   #2

回复#1 @jacen : 文件附件已上传,测试后时间对比如下图。

image.png


附件:附件下载

修改后的处理时间还是比较长修改后如下:

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;
}


2022-03-04   #3

回复#2 @admin :

文件少的话确实没啥,但是文件多了的话,时间累计就比较多了。我这里之前用PowerShell处理过的文件有9K多份。

2022-03-06   #4

可以用新增的 string.keywords

image.png

刚试了下, 会非常快了 , 测试用这个只需要1-2秒时间就完成了.

登录后方可回帖

登 录
信息栏
公告:
私人站, 专注分享, 可在分享中适当提问, 但谢绝纯提问, 否则不再提醒一律删帖, 谢谢合作!



本站域名:HtmLayout.Cn
aardio可以快速开发上位机,本站主要记录了学习过程中遇到的问题和解决办法及aardio代码分享

这里主要专注于aardio学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.

Aardio 官方站:Aardio官方
Aardio最新功能:Aardio官方更新日志
本 站 主 站:Stm32cube中文网
Sciter中文在线文档Sciter在线学习文档
空间赞助:才仁机械
Loading...