一个提取DXF文件 获取图纸信息的半成品~求大佬优化~
By
☜李長新☞
at 2022-03-03 • 0人收藏 • 1106人看过
原理: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:我试了下, 感觉效率还可以啊,是我文件太少太小了吗