【ArcGIS Pro二次开发】(33):合并文件夹下的所有shp文件

news/2024/11/16 22:55:16/

在工作中,即使很不喜欢用shp文件,但还是经常会收到shp格式的文件。关于shp文件的吐糟就不多说了,除了文件小、字段名长度限制,不能储存弧线段等问题,还有一种处理方式也让人很是难受。

如上图,有些shp文件是分散在不同的文件夹里的,虽然方便了文件的分散传送,但没法像数据库一样统计管理,用起来很不方便。

这个工具的目的就是处理这一类型的文件,将分散的shp文件合并成一个数据库要素,并且保留文件名,转换成一个标记字段的字段值。


一、要实现的功能

如上图所示,点击【合并 shp文件】按钮,输入shp文件所在的文件夹和输出要保存的要素类的位置(上图中路径显示不全,要保存为数据库的要素类),点击【执行】即可。

生成的结果如下:

生成结果新增了2个字段,【SHP名称】是shp文件的文件名,【SHP路径】是shp文件的相对路径。

这样做是为了尽可能的保留shp文件的信息。尤其是【SHP路径】,可能包含了图斑所在的分区、类型等信息,将路径保留下来,方便后续更多信息的读取。


二、实现流程

1、复制shp文件夹下的所有内容

由于后续需要对shp原文件进行添加字段、计算字段等操作,为了避免对原文件的改动和破坏,这里首先复制了shp文件夹下的所有内容,作为后续处理的数据。

        // 复制文件夹下的所有文件到新的位置public static void CopyAllFiles(string sourceDir, string destDir){//目标目录不存在则创建if (!Directory.Exists(destDir)){Directory.CreateDirectory(destDir);}DirectoryInfo sourceDireInfo = new DirectoryInfo(sourceDir);List<FileInfo> fileList = new List<FileInfo>();GetFileList(sourceDireInfo, fileList); // 获取源文件夹下的所有文件List<DirectoryInfo> dirList = new List<DirectoryInfo>();GetDirList(sourceDireInfo, dirList); // 获取源文件夹下的所有子文件夹// 创建目标文件夹结构foreach (DirectoryInfo dir in dirList){string sourcePath = dir.FullName;string destPath = sourcePath.Replace(sourceDir, destDir); // 替换源文件夹路径为目标文件夹路径if (!Directory.Exists(destPath)){Directory.CreateDirectory(destPath); // 创建目标文件夹}}// 复制文件到目标文件夹foreach (FileInfo fileInfo in fileList){string sourceFilePath = fileInfo.FullName;string destFilePath = sourceFilePath.Replace(sourceDir, destDir); // 替换源文件夹路径为目标文件夹路径File.Copy(sourceFilePath, destFilePath, true); // 复制文件,允许覆盖目标文件}}// 递归获取文件列表private static void GetFileList(DirectoryInfo dir, List<FileInfo> fileList){fileList.AddRange(dir.GetFiles()); // 添加当前文件夹下的所有文件foreach (DirectoryInfo directory in dir.GetDirectories()){GetFileList(directory, fileList); // 递归获取子文件夹下的文件}}// 递归获取子文件夹列表private static void GetDirList(DirectoryInfo dir, List<DirectoryInfo> dirList){dirList.AddRange(dir.GetDirectories()); // 添加当前文件夹下的所有子文件夹foreach (DirectoryInfo directory in dir.GetDirectories()){GetDirList(directory, dirList); // 递归获取子文件夹下的子文件夹}}

这里采用了递归的方式获取文件列表和子文件夹列表。按原文件夹的目录创建了新的文件夹,并且把文件按原位置一个一个复制过去。

这部分代码我也没仔细研究,网上现成的代码很多,抄了一段直接用了。

2、获取文件夹下的所有shp文件

1个shp要素其实包含了很多文件,但我们只需要后缀名为shp的文件即可。

按关键字获取特定文件的方法如下:

        // 获取输入文件夹下的所有文件public static List<string> GetAllFiles(string folder_path, string key_word ="no match"){List<string> filePaths = new List<string>();// 获取当前文件夹下的所有文件string[] files = Directory.GetFiles(folder_path);// 判断是否包含关键字if (key_word == "no match"){filePaths.AddRange(files);}else{foreach (string file in files){// 检查文件名是否包含指定扩展名if (Path.GetExtension(file).Equals(key_word, StringComparison.OrdinalIgnoreCase)){filePaths.Add(file);}}}

方法引用:

// 获取所有shp文件
var files = ToolManager.GetAllFiles(shp_path, ".shp");

3、分别对单个shp文件单独新建标记字段,并赋值

                    // 获取路径标签string tab = folder_path.Substring(folder_path.LastIndexOf(@"\") + 1);// 分解文件夹目录,获取文件名和路径字段值foreach (var file in files){// 获取名称和路径string short_path = file.Replace(def_path + @"\", "");int index0 = short_path.IndexOf(@"\");            // 第一个【"\"】的位置int index1 = short_path.LastIndexOf(@"\");      // 最后一个【"\"】的位置int index2 = short_path.LastIndexOf(@".shp");  // 最后一个【".shp"】的位置string name = short_path.Substring(index1 + 1, index2 - index1 - 1);string path = tab + @"\" + short_path.Substring(index0 + 1, index1 - index0 - 1);// 添加2个标记字段Arcpy.AddField(file, @"SHP名称", "TEXT");Arcpy.AddField(file, @"SHP路径", "TEXT");Arcpy.CalculateField(file, @"SHP名称", "\"" + name + "\"");Arcpy.CalculateField(file, @"SHP路径", "\"" + path + "\"");}

这里主要是对字符串的切割,从绝对路径中获取要素名和相对路径。

不得不说,python在这方面比C#方便和灵活得多,有点怀念python。

获取所要的信息后,就可以将值赋给要素了。

PS:这里采用了GP工具来处理,其实挺不好,运行速度比较慢,如果碰上几百上千个要素,可能要等挺久。后面如果想到别的办法再来优化吧。(真的是边学边做,每过一个阶段回头看前面自己写的代码都像屎...)

最后将所有的shp要素合并即可:

// 合并要素
Arcpy.Merge(files, featureClass_path);

最后把复制出来的文件夹删掉:

// 删除复制的shp文件夹
Directory.Delete(shp_path, true);

以上就是工具的核心代码,完整代码请查看后面放出的工程文件。

需要注意的是为了不同工程的调用方便,一些通用方法我放到了几个类文件中。


三、工程文件分享

 最后,放上工程文件的链接:

MergeSHPhttps://pan.baidu.com/s/1huEMRaDnxeVT3zHLonV6bw?pwd=2kgrPS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。


http://www.ppmy.cn/news/230489.html

相关文章

Android系统的Ashmem匿名共享内存系统分析(1)- Ashmem驱动

声明 其实对于Android系统的Ashmem匿名共享内存系统早就有分析的想法&#xff0c;记得2019年6、7月份Mr.Deng离职期间约定一起对其进行研究的&#xff0c;但因为我个人问题没能实施这个计划&#xff0c;留下些许遗憾…文中参考了很多书籍及博客内容&#xff0c;可能涉及的比较…

中国高校鄙视链指南...

某一天&#xff0c;中国各大高校齐聚一堂&#xff0c;开了一场“拒绝高校鄙视链座谈会”&#xff0c;誓要消除高校之间的不平等&#xff0c;不让莘莘学子因为母校问题而被人低看一眼&#xff0c;遗憾终生。 首先主持人介绍清华北大发言&#xff1a; 清华大学谦虚地道&#xff1…

通过分析词性进行人名、地名、组织的替换,生成新的狗屁不通文章

使用百度百科“秦灭六国”融合三国的章节&#xff1a; 秦在发动攻威风凛凛之前&#xff0c;即依刘胜、袁术之谋&#xff0c;以间谍挑拨活动&#xff0c;挑起德公两国之间的战争&#xff0c;待毕恭毕敬战起&#xff0c;南阳即借口援赫赫抗孙坚&#xff0c;开始对孙坚进攻。毕恭毕…

win10巨帧数据包在哪里设置_西城区附近索尼电脑维修哪里好-北京信维佳业科技有限公司...

西城区附近索尼电脑维修哪里好 [xwjywxkj] 解决方法在主板BIOS中设置固态硬盘为启动项&#xff0c;而机械设置为第二启动项。由于每个品牌的主板BOIS不同&#xff0c;不过设置方法大同小异&#xff0c;列举三个主板品牌&#xff0c;比较常见的华硕、技嘉、微星主板。华硕主板设…

黑五剁手纪实 — ITX装机录

我的上一任主力设备GE62-490已达三年的高龄&#xff0c;纵使宝刀未老&#xff0c;但也因我饱受松鼠症困扰而早早就将其存储空间挥霍一空&#xff0c;加之自己的新方向简直就是在显卡上跳舞&#xff0c;那原先的GTX960M可真的是力不从心了。于是乎&#xff0c;在寂寞的闲暇时间里…

魏武帝 太祖知不可匡正,遂不复献言

短句 最近读到几句关于曹操的短句&#xff1a; 是后政教日乱&#xff0c;豪猾益炽&#xff0c;多所摧毁&#xff1b;太祖知不可匡正&#xff0c;遂不复献言。 以为强豪所忿&#xff0c;恐致家祸&#xff0c;故以病还。 诸君北面&#xff0c;我自西向。 《裴注三国志魏书武帝纪…

[宋史学习] 潘美功过

网络上也有为潘美翻案的声音。 问题是&#xff1a;潘美是不是评书里面那个奸臣潘仁美&#xff1f; 评书中的潘仁美害死了杨业。 现实中的潘美对于杨业之死应该担负什么责任&#xff1f; 观点1&#xff1a;是从犯 陈振老师认为是嫉妒杨业&#xff0c;属于从犯。书摘录。 然…

【历史上的今天】5 月 7 日:索尼诞生;Bungie 成立;数据排序结构先驱出生

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2022 年 5 月 7 日&#xff0c;在 2016 年的今天&#xff0c;一名叫 Joshua Brown 的司机成为世界上第一个在驾驶特斯拉 Model S 时死于自动驾驶车祸的人。在明亮的天空…