一个提取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
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秒时间就完成了.

登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...