Shape文件批量导入File GeoDatabase

开始学习Python有几天的时间了,这些天每天对着电脑看枯燥的代码,自己都快崩溃了,终于功夫不负有心人,写出了自己的第一个批量处理工具:将文件夹中的shape文件批量导入到ArcGIS的File GeoDatabase中。工具界面如图一:

图一    Shape批量导入File GDB工具界面
图一    Shape批量导入File GDB工具界面

从图一看到,工具的界面并不复杂,只需要制定shape文件所在的文件夹和File GDB保存的路径就可以了。通过该工具,可以将指定文件夹根目录下所有的Shape文件和第一级子目录中所有的Shape文件转换到与根目录同名的File GDB数据库中,第一级子目录会转换为FileGDB中同名的Feature Dateset。此工具要求根目录及一级子目录中只能有Shape文件,子目录可以为空,但是空子目录同样会被转换为Feature Dateset。一级子目录中的Shape文件最好都具有相同的坐标系统。FileGDB存储的路径不能与输入的存储shape数据的路径相同,最好也不要放在它的子目录中。

因为是第一次制作工具,所以将代码贴出来,大家一同学习,欢迎批评指正。

# 导入系统模块
#
import sys
import os
import arcgisscripting
gp = arcgisscripting.create(9.3)
# 定义工作空间
# 
Workspace = sys.argv[1]
gp.Workspace = Workspace
# 定义输出路径
# 
Output_GDB_Path = sys.argv[2]
# 覆盖已存在文件
# 
gp.OverWriteOutput = 1
# 定义File GDB位置和名称
# 
File_GDB = Output_GDB_Path + os.sep + os.path.basename(gp.Workspace) + ".gdb"
# 创建File GDB
# 
gp.CreateFileGDB(Output_GDB_Path, os.path.basename(File_GDB))
# 打印数据库创建成功信息
# 
gp.AddMessage("++++++++++++++++++++++++++++")
gp.AddMessage("数据库创建成功")
# 读取工作空间下的所有shape文件
# 
Feature_Classes = gp.ListFeatureClasses()
# 计算shape文件个数
# 
count1 = len(Feature_Classes)
# 如果文件夹下存在shape文件,则逐个读取文件,并存入上面新建的FIleGDB中
# 
if count1 > 0:
    for Feature_Class in Feature_Classes:
        gp.CopyFeatures_management(Feature_Class,File_GDB + os.sep + Feature_Class[:-4])
# 读取工作空间下的文件夹
# 
Folder_Lists = os.listdir(gp.Workspace)
# 如果工作空间下存在文件夹,则逐个读取文件夹名称
# 
for Folder_List in Folder_Lists:
    List_Element = gp.Workspace + os.sep + Folder_List
	# 如果读取的文件夹确实存在,则用文件夹名称建立要素数据集
	# 
    if os.path.isdir(List_Element):
        gp.workspace = gp.workspace + os.sep + Folder_List
        gp.CreateFeatureDataset_management(File_GDB,Folder_List)
        gp.AddMessage("++++++++++++++++++++++++++++")
        gp.AddMessage("要素数据集" + str(Folder_List) + "创建成功!")
		# 读取子目录中的shape文件,并确定shape文件个数
		# 
        Feature_Classes = gp.ListFeatureClasses()
        count2 = len(Feature_Classes)
		# 如果确实存在shape文件,则将子目录中的shape文件导入到要素数据集中
		# 
        if count2 > 0:
            for Feature_Class in Feature_Classes:
                gp.CopyFeatures_management(Feature_Class,File_GDB + os.sep + Folder_List + os.sep + Feature_Class[:-4])
            gp.AddMessage("++++++++++++++++++++++++++++")
            gp.AddMessage(str(Folder_List) + "中所有文件复制完毕!")
			# 读取shape文件的空间坐标系统
			# 
            Dateset_SF = gp.describe(Feature_Class).SpatialReference
			# 将shape文件的空间坐标系统赋予要素数据集
			# 
            gp.DefineProjection_management(File_GDB + os.sep + Folder_List, Dateset_SF)
            gp.AddMessage("++++++++++++++++++++++++++++")
            gp.AddMessage(str(Folder_List) + "坐标系统定义成功!")
        gp.workspace = Workspace

上述代码是基于ArcGIS 9.x平台,在ArcGIS 10.x平台上运行情况未知。为此,笔者重写了代码,使其可以运行在ArcGIS10及以上的版本中。程序要求各文件夹中准备导入FileGDB的shape文件不存在重名情况,这主要是受FileGDB的特性影响,因此在导入数据前,会先进行检查,如果存在重名情况,会强行终止程序。另外,程序会覆盖已存在的数据库及文件,因此建议不要提前建立数据库,让程序自己建立即可。对于没有shapefile的空文件夹,不会建立同名Dataset。

# -*- coding: utf-8 -*-
import os,sys
import arcpy
from arcpy import env


def check_in_shps(in_path):
    print(u"开始检查输入的shapefile...")
    shps_list = {}
    env.workspace = in_path
    root_shps = arcpy.ListFeatureClasses()
    for root_shp in root_shps:
        shps_list[root_shp] = in_path
    sub_folders = os.listdir(in_path)
    for sub_folder in sub_folders:
        if os.path.isdir(os.path.join(in_path,sub_folder)):
            env.workspace = os.path.join(in_path, sub_folder)
            sub_folder_shps = arcpy.ListFeatureClasses()
            for sub_folder_shp in sub_folder_shps:
                if sub_folder_shp not in shps_list.keys():
                    shps_list[sub_folder_shp] = os.path.join(in_path,sub_folder)
                else:
                    print(u"文件夹\"%s\"中的\"%s\"与\"%s\"中的文件重名!\n" % (sub_folder, sub_folder_shp,shps_list[sub_folder_shp]))
                    shps_list = None
                    sys.exit()
        else:
            continue
    print(u"输入的shapefile符合要求,开始将数据导入FileGDB。\n")
    shps_list = None


def copy_shps_to_filegdb(in_path, out_filegdb):
    check_in_shps(in_path)
    if arcpy.Exists(out_filegdb) == 0:
        arcpy.CreateFileGDB_management(os.path.split(out_filegdb)[0], 
                                       os.path.split(out_filegdb)[1], 
                                       "9.3")
        print(u"指定的数据库不存在,已为您创建!\n")

    env.overwriteOutput = True
    env.workspace = in_path

    root_shps = arcpy.ListFeatureClasses()
    print(u"开始处理根目录下的shapefile...")
    for root_shp in root_shps:
        out_shp_path = out_filegdb + os.sep + os.path.splitext(root_shp)[0]
        arcpy.CopyFeatures_management(root_shp, out_shp_path)
        print(u"  -\"%s\"已成功导入数据库!" % root_shp)
    print(u"根目录下的shapefile已经处理完毕!\n")

    sub_folders = os.listdir(in_path)
    for sub_folder in sub_folders:
        if os.path.isdir(os.path.join(in_path,sub_folder)):
            env.workspace = os.path.join(in_path,sub_folder)
            env.overwriteOutput = True
            sub_folder_shps_list = []
            sub_folder_shps  = arcpy.ListFeatureClasses()
            for sub_folder_shp in sub_folder_shps:
                sub_folder_shp = os.path.join(env.workspace,sub_folder_shp)
                sub_folder_shps_list.append(sub_folder_shp)
            if len(sub_folder_shps_list) == 0:
                print(u"\"%s\"目录为空,不创建任何数据集!\n" % sub_folder)
                continue
            else:
                if arcpy.Exists(out_filegdb + os.sep + sub_folder):
                    print(u"数据集\"%s\"已存在,将覆盖其中的数据!!!" % sub_folder)
                else:
                    print(u"开始处理\"%s\"文件夹下的shapefile..." % sub_folder)
                    arcpy.CreateFeatureDataset_management(out_filegdb, 
                                                          sub_folder, 
                                                          sub_folder_shps_list[0])
                for sub_folder_shp in sub_folder_shps_list:
                    out_fc_name = os.path.splitext(os.path.split(sub_folder_shp)[1])[0]
                    arcpy.CopyFeatures_management(sub_folder_shp, 
                                                  os.path.join(out_filegdb,sub_folder,out_fc_name))
                    print(u"  -\"%s.shp\"已成功导入数据库!" % out_fc_name)
                print(u"文件夹\"%s\"下的shapefile已经处理完毕!\n" % sub_folder)
    print(u"所有shapefile处理完毕!\n")


if __name__ == "__main__":
    in_path = u"D:\\path\\to\\folder"
    out_filegdb = u"D:\\path\\to\\filegdb"
    copy_shps_to_filegdb(in_path, out_filegdb)

大家可以移步本站下载区下载该ArcToolbox工具,有任何问题欢迎反馈。该工具在ArcGIS 9.3.1下测试通过。

17 comments

  1. 按照你的方法,我是了一下,还是不行!可能和我的运行环境有关系吧!再次站长的帮助

      1. 今天换了台电脑运行没有问题了!非常感谢!
        就是感觉运行速度稍微有点慢,呵呵!我想如果引用featureclass to geodatabase会不会快一点,呵呵!个人建议,没有试验过,呵呵!再次感谢站长的帮助!

  2. 这个工具很实用!本人刚刚接触python,菜鸟一个,我想请教一下:一个文件夹下有多个子文件,每个子文件中有多个shp,我想把每个子文件夹中的shp文件导入一个以子文件夹命名的mdb中!(即以子文件名创建mdb数据库,然后顺便名称(如ds等)建立数据集,我子文件中的shp导入mdb数据库的数据集(ds)中),最后就是实现了每个子文件夹中的shp文件都导入各自的mdb中,而不是把所有数据都导入一个数据库中,不知道这个代码应该怎样写?望赐教!!

      1. 非常感谢您的帮助,我刚刚试了一下,运行会提示错误
        我在arcgis9.3 sp1的运行环境运行之后,刚刚创建数据库之后,就出现999998的错误。

        下面是运行的结果!
        Executing: shape2MDB D:tts “D:New Folder”
        Start Time: Fri May 04 21:35:31 2012
        Running script shape2MDB…
        >>===============BEGIN=================
        > WorkSpace: D:ttsG48
        > Personal GeoDatabase “D:ttsG48” Create Successful!!!
        ERROR 999998: Unexpected Error.
        Failed to execute (shape2MDB).
        End Time: Fri May 04 21:35:33 2012 (Elapsed Time: 2.00 seconds)

        1. 我是在ArcGIS 9.3.1下测试的。你是直接下载的ArcToolbox工具,还是通过源代码重新编译的?

        2. 参考一下这个:http://webhelp.esri.com/arcgisdesktop/9.3/index.cfm?topicname=tool_errors_and_warnings:999998-999999

        3. 你也可以这样,把那个py文件进行编译,直接运行,而不要用Toolbox工具。修改其中的
          INPUT_fOLDER_PATH = gp.GetParameterAsText(0)
          OUTPUT_FOLDER_PATH = gp.GetParameterAsText(1)
          两行,将gp.GetParameterAsText(0)和gp.GetParameterAsText(1)改为输入和输出的文件地址,形式是这样的:r”D:ttsG48″

        4. 我在9.3.1下测试通过,下面是日志:
          Executing: shape2MDB G:progSHP2GDB G:progaaaa
          Start Time: Sat May 05 00:13:27 2012
          Running script shape2MDB…
          >>===============BEGIN=================
          > WorkSpace: G:progSHP2GDBline
          > Personal GeoDatabase “line.mdb” Create Successful!!!
          > “geol.shp” Copy to line.mdb Successful!!!
          > “geolstr5000.shp” Copy to line.mdb Successful!!!
          > “line_Create.shp” Copy to line.mdb Successful!!!
          > WorkSpace: G:progSHP2GDBpoint
          > Personal GeoDatabase “point.mdb” Create Successful!!!
          > “Export_Output_2.shp” Copy to point.mdb Successful!!!
          > WorkSpace: G:progSHP2GDBpolygon
          > Personal GeoDatabase “polygon.mdb” Create Successful!!!
          > “standb4.shp” Copy to polygon.mdb Successful!!!
          > “standb4_clip.shp” Copy to polygon.mdb Successful!!!
          > “stbuff5000.shp” Copy to polygon.mdb Successful!!!
          >>================END==================
          Completed script shape2MDB…
          Executed (shape2MDB) successfully.
          End Time: Sat May 05 00:14:24 2012 (Elapsed Time: 57.00 seconds)
          经过测试,之前的错误是因为有空文件夹的事情。

Comments are closed.