arcpy使用
寫在前面
地理處理框架與arcpy
arcgis地理處理包括了查找工具、工具箱、地理處理環(huán)境、模型、python腳本、arcpy等一系列自動執(zhí)行地理任務(wù)的框架。
arcpy是esri針對arcgis系列產(chǎn)品做的一個python站點包,它像膠水一樣黏貼了多個與arcgis應(yīng)用程序相關(guān)的arc objects函數(shù)對象,我們甚至可以從幫助里找到toolbox每個工具箱的代碼原型。arcpy涉及地理數(shù)據(jù)分析、數(shù)據(jù)轉(zhuǎn)換、數(shù)據(jù)管理和地圖自動化等地理處理業(yè)務(wù)。使用python和arcpy的好處在于能夠?qū)⒍鄠€地理處理工具組織一起,匯聚成一個工作流,解決一些復(fù)雜的地理處理工作。并可以將工作流打包成地理處理包或者創(chuàng)建地理處理服務(wù),與他人共享使用。
Python語言
Python語言包含了數(shù)字、字符串、語句、表達(dá)式、控制語句(條件語句、分支語句、循環(huán)語句)、對象、函數(shù)等基本要素以及編寫python語句的基本語法和范式。但是這些東西也沒必要面面俱到,因為光是《python library reference》,就有1000多頁,你得翻到什么時候。了解Python基本組成部分如字符串處理、路徑、控制語句、模塊、對象、函數(shù)和常用的編碼規(guī)范即可,邊用邊學(xué)。
本文按照arcpy編寫環(huán)境、站點包引入、地理處理工具函數(shù)和非工具函數(shù)、空間數(shù)據(jù)訪問和處理、創(chuàng)建地理處理工具、構(gòu)建地理處理模型、共享地理處理服務(wù)講述arcpy使用的全過程。arcpy編寫環(huán)境、站點包引入、地理處理工具函數(shù)和非工具函數(shù)、空間數(shù)據(jù)訪問和處理是編寫arcpy腳本過程;創(chuàng)建地理處理工具、構(gòu)建地理處理模型是制作腳本工具過程;共享地理處理服務(wù)是將腳本工具發(fā)布為地理處理服務(wù)過程。其中,地理處理函數(shù)和非工具函數(shù)涉及內(nèi)容重復(fù)性過多,不能一一列舉,但它也是arcpy最豐富、最出彩的地方,之所以把地理處理工具函數(shù)和非工具函數(shù)放在數(shù)據(jù)訪問前面,也是因為如此。很多時候,地理處理函數(shù),甚至都看不到專有數(shù)據(jù)驅(qū)動,就直接處理數(shù)據(jù)了。由于大部分地理處理過程需要用到python中的數(shù)據(jù)類型、函數(shù)、控制語句、類型等來連貫地理處理函數(shù)及數(shù)據(jù)處理過程,python相關(guān)內(nèi)容也需補(bǔ)充的。
一、制作地理處理腳本
地理處理:arcpy編寫環(huán)境
在安裝arcgis的過程中,一般都會提示你安裝python2.7。這個其實就是在讓我們給arcpy安裝一個自帶的語言編寫環(huán)境。
以上是在arcgis安裝完成后,python2.7自帶的站點包,里面包含了諸如osgeo、numpy、pandas、pil等遙感影像處理常用的開源站點包。還有如pip這樣的Python 包管理工具,用于站點包的查找、下載、安裝、卸載等。arcpy工具包放在另外一個位置,該工具包從文件表現(xiàn)形式上有,arengine\acrserver\arceditor等等,arcpy工具包如下:
我們先來看一下python2.7的IDE工具,也就是用于引用arcpy的編寫工具:
倒數(shù)第二個圖標(biāo)就是python的IDE,可以打開來看一下。
這個IDE以命令行的方式呈現(xiàn),我們可以按照python語法鍵入一條語句。
import this?
python在引入包(python中特定的工具集)的時候,需要使用關(guān)鍵字import?引入,如下:
也可以打開arccatalog或者arcmap,交互式進(jìn)入命令行窗口:
一般而言,如果使用命令行的方式,是我們寫一條語句,回車,程序執(zhí)行一條語句,再寫一句,再回車,程序再執(zhí)行一條語句。實際情況是我們總希望把一個完整的業(yè)務(wù)邏輯全部寫下來,讓程序一次性執(zhí)行完畢,這時候我們就需要腳本。幾乎所有帶有.py的文件都可以是python的腳本 。我們可以使用記事本、notepad、python gui、pycharm、vs等工具編寫python語句,最后保存為.py的文件,然后使用編譯器python.exe解釋,在cmd中鍵入python xx.py后回車確認(rèn),得到運行結(jié)果。
前提你把python.exe路徑加入系統(tǒng)變量了
? ??
或者在IDE中,在new file 按鈕上新建文件,鍵入print("hellow the world")
一個簡單完整的地理處理腳本編寫過程如下:
import arcpy #arcpy站點包導(dǎo)入 arcpy.env.workspace = "C:/Workspace" #設(shè)置工作空間arcpy.Clip_management("image.tif","1952602.23 294196.279 1953546.23 296176.279","clip.gdb/clip", "#", "#", "NONE") # 執(zhí)行地理處理工程,此處是柵格裁剪地理處理:arcpy站點包引入
導(dǎo)入arcpy站點包語句為(imprt是python中導(dǎo)入站點包、函數(shù)、模塊的關(guān)鍵字,一般需要設(shè)置系統(tǒng)訪問路徑):
import arcpyarcpy以地理處理工具包、函數(shù)集、模塊、類等組織在一起,結(jié)構(gòu)如下:
arcpy組成部分描述如下:
| ArcPy | ArcPy(通常稱為 ArcPy 站點包),為用戶提供了使用 Python 語言操作所有地理處理工具(包括擴(kuò)展模塊)的接口,并提供了多種有用的函數(shù)和類,以用于處理和詢問 GIS 數(shù)據(jù)。使用 Python 和 ArcPy,可以開發(fā)出大量的用于處理地理數(shù)據(jù)的實用程序。 |
| ArcPy 模塊 | 模塊通常是一個包含函數(shù)和類的 Python 文件。ArcPy 由一系列模塊支持,包括數(shù)據(jù)訪問模塊?(arcpy.da)、制圖模塊?(arcpy.mapping)、ArcGIS Spatial Analyst 擴(kuò)展模塊 模塊?(arcpy.sa) 以及?ArcGIS Network Analyst 擴(kuò)展模塊 模塊?(arcpy.na)。 |
| ArcPy 類 | 類的作用類似于建筑設(shè)計藍(lán)圖。藍(lán)圖為如何創(chuàng)建事物提供了一個框架,類可用于創(chuàng)建對象,即通常所說的實例。ArcPy 類,如?SpatialReference?和?Extent類,通常用作地理處理工具參數(shù)設(shè)置的快捷方式,否則的話,這些參數(shù)會使用更加復(fù)雜的字符串。 |
| ArcPy 函數(shù) | 函數(shù)是用于執(zhí)行某項特定任務(wù)并能夠納入更大的程序的已定義功能。 在 ArcPy 中,所有地理處理工具均以函數(shù)形式提供,但并非所有函數(shù)都是地理處理工具。除工具之外,ArcPy 還提供多種函數(shù)來更好地支持 Python 地理處理工作流。函數(shù)(通常稱為方法)可用于列出某些數(shù)據(jù)集、檢索數(shù)據(jù)集的屬性、在將表添加到地理數(shù)據(jù)庫之前驗證表名稱,或執(zhí)行其他許多有用的腳本任務(wù)。 |
如果需要用到包里的一部分類、對象、或者函數(shù),可以寫為:
from arcpy import env
也可將類、對象、模塊進(jìn)行標(biāo)識(取名):
from arcpy import env? as myenv
myenv.workspace="c:/data"
arcpy站點包還包含了許多模塊,如自動化制圖模塊(arcpy.mapping) 和數(shù)據(jù)訪問模塊(arcpy.da),導(dǎo)入方式如下:
import arcpy.mapping
編寫python腳本前,需設(shè)置當(dāng)前工作空間,如:
import arcpy?
arcpy.env.workspace="c:/data"
注:路徑表達(dá)方式一般有三種
斜杠:
"c:/data"
反斜杠:
"c:\\data"
特殊字符r:
r"c:\data"
“\”在編碼中需轉(zhuǎn)義,前面加r,直接按照原文意思輸出。
地理處理:地理處理工具函數(shù)和非工具函數(shù)
工具
地理處理工具是指arcgis軟件工具箱中工具的統(tǒng)稱,每個工具都會給出相應(yīng)的圖形界面、使用幫助和arcpy語法和使用方式,比如矢量裁剪工具:
打開空間分析的裁剪工具圖形界面:
打開裁剪工具幫助:
裁剪工具語法結(jié)構(gòu):
Clip_analysis (in_features, clip_features, out_feature_class, {cluster_tolerance})
| 參數(shù) | 說明 | 數(shù)據(jù)類型 |
| in_features | 要裁剪的要素。 | Feature Layer |
| clip_features | 用于裁剪輸入要素的要素。 | Feature Layer |
| out_feature_class | 待創(chuàng)建的要素類。 | Feature Class |
| cluster_tolerance (可選) | 所有要素坐標(biāo)之間的最小距離以及坐標(biāo)可以沿 X 和/或 Y 方向移動的距離。如果此值設(shè)置得較高,則數(shù)據(jù)的坐標(biāo)精度將會較低;如果此值設(shè)置得較低,則數(shù)據(jù)的坐標(biāo)精度將會較高。 | Linear unit |
裁剪工具腳本代碼:
import arcpy from arcpy import env# Set workspace env.workspace = "C:/data"# Set local variables in_features = "majorrds.shp" clip_features = "study_quads.shp" out_feature_class = "C:/output/studyarea.shp" xy_tolerance = ""# Execute Clip arcpy.Clip_analysis(in_features, clip_features, out_feature_class, xy_tolerance)地理處理工具以錘子狀的圖標(biāo)形式呈現(xiàn),有相關(guān)的圖形界面和代碼表現(xiàn)方式(如裁剪工具:arcpy.Clip_analysis()),我們在使用arcgis過程中經(jīng)常用到工具箱,此處不詳細(xì)說,我們側(cè)重描述arcpy代碼部分。
確切的說,arcpy地理處理工具是一個python腳本函數(shù),該類函數(shù)可以直接調(diào)用并進(jìn)行相關(guān)地理處理。
一個完整的地理處理腳本包含函數(shù)名和調(diào)用參數(shù)。調(diào)用參數(shù)一般有輸入?yún)?shù)、輸出參數(shù)和附加參數(shù)。附加參數(shù)常常指處理過程中的設(shè)置條件,如上述的裁剪函數(shù)的附加參數(shù)是容差{cluster_tolerance}。在裁剪時,我們有可能需要設(shè)置裁剪的容差。很多時候,設(shè)置條件是默認(rèn)選項,不需要進(jìn)行設(shè)置。
地理處理工具腳本按照地理處理功能分類,有數(shù)據(jù)管理、數(shù)據(jù)轉(zhuǎn)換、地理編碼、地理分析、地理統(tǒng)計、服務(wù)器工具等大類和幾百個工具函數(shù),應(yīng)當(dāng)在具體應(yīng)用是細(xì)細(xì)體會。
地理處理工具腳本具體調(diào)用方式有兩種。
(1)按照命名方式逐層展開調(diào)用,工具箱和函數(shù)以點號隔開,如:
? ? ? ? ?arcpy.analysis.Clip()
(2)按照函數(shù)直接調(diào)用,函數(shù)和工具箱用_隔開,如:
? ? ? ? arcpy.Clip_analysis()
其中,analysis是Analysis Tools(分析工具)別名。很多時候我們記不住他們的名字,可以對著工具箱屬性查閱。。
非工具函數(shù)
正如官方描述所述:在 ArcPy 中,所有地理處理工具均以函數(shù)形式提供,但并非所有函數(shù)都是地理處理工具。除工具之外,ArcPy 還提供多種函數(shù)來更好地支持 Python 地理處理工作流。函數(shù)(通常稱為方法)可用于列出某些數(shù)據(jù)集、檢索數(shù)據(jù)集的屬性、在將表添加到地理數(shù)據(jù)庫之前驗證表名稱,或執(zhí)行其他許多有用的腳本任務(wù)。函數(shù)比較多,具體用用時查詢。
| AcceptConnections | 地理數(shù)據(jù)庫管理 |
| AddDataStoreItem | 數(shù)據(jù)存儲 |
| AddError | 消息和錯誤處理 |
| AddFieldDelimiters | 字段 |
| AddIDMessage | 消息和錯誤處理 |
| AddMessage | 消息和錯誤處理 |
| AddReturnMessage | 消息和錯誤處理 |
| AddToolbox | 工具和工具箱 |
| AddWarning | 消息和錯誤處理 |
| AlterAliasName | 常規(guī) |
| AsShape | 幾何 |
| CheckExtension | 許可授予和安裝 |
| CheckInExtension | 許可授予和安裝 |
| CheckOutExtension | 許可授予和安裝 |
| CheckProduct | 許可授予和安裝 |
| ClearEnvironment | 環(huán)境和設(shè)置 |
| Command | 常規(guī) |
| CopyParameter | 獲取和設(shè)置參數(shù) |
| CreateObject | 常規(guī) |
| CreateGeocodeSDDraft | 發(fā)布 |
| CreateGPSDDraft | 發(fā)布 |
| CreateImageSDDraft | 發(fā)布 |
| CreateRandomValueGenerator | 常規(guī) |
| CreateScratchName | 常規(guī)數(shù)據(jù)函數(shù) |
| CreateSQLiteDatabase | 工作空間 |
| CreateUniqueName | 常規(guī)數(shù)據(jù)函數(shù) |
| DecryptPYT | 工具和工具箱 |
| 描述 | 描述數(shù)據(jù) |
| DisconnectUser | 地理數(shù)據(jù)庫管理 |
| EncryptPYT | 工具和工具箱 |
| Exists | 常規(guī)數(shù)據(jù)函數(shù) |
| FromWKB | 幾何 |
| FromWKT | 幾何 |
| GetActivePortalURL | ArcGIS Online/Portal |
| GetArgumentCount | 獲取和設(shè)置參數(shù) |
| GetIDMessage | 消息和錯誤處理 |
| GetImageEXIFProperties | 柵格 |
| GetInstallInfo | 許可授予和安裝 |
| GetLogHistory | 日志歷史 |
| GetMaxSeverity | 消息和錯誤處理 |
| GetMessage | 消息和錯誤處理 |
| GetMessageCount | 消息和錯誤處理 |
| GetMessages | 消息和錯誤處理 |
| GetPackageInfo | 打包 |
| GetParameter | 獲取和設(shè)置參數(shù) |
| GetParameterAsText | 獲取和設(shè)置參數(shù) |
| GetParameterCount | 獲取和設(shè)置參數(shù) |
| GetParameterInfo | 獲取和設(shè)置參數(shù) |
| GetParameterValue | 獲取和設(shè)置參數(shù) |
| GetReturnCode | 消息和錯誤處理 |
| GetSeverity | 消息和錯誤處理 |
| GetSeverityLevel | 消息和錯誤處理 |
| GetSigninToken | ArcGIS Online/Portal |
| GetSystemEnvironment | 環(huán)境和設(shè)置 |
| GetUTMFromLocation | 空間參考和變換 |
| ImportToolbox | 工具和工具箱 |
| InsertCursor | 游標(biāo) |
| IsSynchronous | 工具和工具箱 |
| ListDatasets | 列出數(shù)據(jù) |
| ListDataStoreItems | 數(shù)據(jù)存儲 |
| ListEnvironments | 環(huán)境和設(shè)置 |
| ListFeatureClasses | 列出數(shù)據(jù) |
| ListFields | 列出數(shù)據(jù) |
| ListFiles | 列出數(shù)據(jù) |
| ListIndexes | 列出數(shù)據(jù) |
| ListInstallations | 許可授予和安裝 |
| ListPortalURLs | ArcGIS Online/Portal |
| ListPrinterNames | 常規(guī) |
| ListRasters | 列出數(shù)據(jù) |
| ListSpatialReferences | 空間參考和變換 |
| ListTables | 列出數(shù)據(jù) |
| ListToolboxes | 工具和工具箱 |
| ListTools | 工具和工具箱 |
| ListTransformations | 空間參考和變換 |
| ListUsers | 地理數(shù)據(jù)庫管理 |
| ListVersions | 列出數(shù)據(jù) |
| ListWorkspaces | 列出數(shù)據(jù) |
| LoadSettings | 環(huán)境和設(shè)置 |
| NumpyArrayToRaster | 柵格 |
| ParseFieldName | 字段 |
| ParseTableName | 常規(guī)數(shù)據(jù)函數(shù) |
| ProductInfo | 許可授予和安裝 |
| RasterToNumPyArray | 柵格 |
| RefreshActiveView | 常規(guī) |
| RefreshCatalog | 常規(guī) |
| RefreshTOC | 常規(guī) |
| RemoveDataStoreItem | 數(shù)據(jù)存儲 |
| RemoveToolbox | 工具和工具箱 |
| ResetEnvironments | 環(huán)境和設(shè)置 |
| ResetProgressor | 進(jìn)度對話框 |
| SaveSettings | 環(huán)境和設(shè)置 |
| SearchCursor | 游標(biāo) |
| SetLogHistory | 日志歷史 |
| SetParameter | 獲取和設(shè)置參數(shù) |
| SetParameterAsText | 獲取和設(shè)置參數(shù) |
| SetProduct | 許可授予和安裝 |
| SetProgressor | 進(jìn)度對話框 |
| SetProgressorLabel | 進(jìn)度對話框 |
| SetProgressorPosition | 進(jìn)度對話框 |
| SetSeverityLevel | 消息和錯誤處理 |
| TestSchemaLock | 常規(guī)數(shù)據(jù)函數(shù) |
| UpdateCursor | 游標(biāo) |
| Usage | 常規(guī) |
| ValidateDataStoreItem | 數(shù)據(jù)存儲 |
| ValidateFieldName | 字段 |
| ValidateTableName | 常規(guī)數(shù)據(jù)函數(shù) |
地理處理:空間數(shù)據(jù)的訪問
通用性訪問
無論我們使用什么樣的工具,首先第一步就是訪問數(shù)據(jù)。空間數(shù)據(jù)的訪問既可以是軟件訪問,也可以是代碼方式訪問。在軟件方面,有如:arcgisd,mapinfo、QGIS、GRASS GIS uDig等,代碼庫方式訪問有arcpy、GDAL/OGR、Spectral Python、GeoPandas、GEOS等等。當(dāng)然編碼語言本身也能訪問空間數(shù)據(jù),但是我們需要很清楚地知道數(shù)據(jù)本身的結(jié)構(gòu)(如python 中的open\read\write函數(shù))。
按照存儲模型的不同,一般將空間數(shù)據(jù)分為矢量數(shù)據(jù)和柵格數(shù)據(jù)(你也可以按照維度把數(shù)據(jù)分為二維數(shù)據(jù)或者三維數(shù)據(jù)),兩種類型的數(shù)據(jù)(柵格數(shù)據(jù)包含影像數(shù)據(jù))有著不同的訪問方式,即便是矢量數(shù)據(jù)或者柵格數(shù)據(jù),也因為廠商或者標(biāo)準(zhǔn)的不一樣,也有著不同的訪問方式。如影像:tif,img,bmp,HDF等格式。相對而言,影像比較容易訪問,影像內(nèi)部存儲順序一般比較規(guī)律:BSQ 、BIL、BIP,只要知道行列號,波段數(shù)目、像元深度,即可方便地訪問每個像元值,而矢量數(shù)據(jù)的關(guān)鍵性信息不僅有行列號、字段值,還需知道字段的數(shù)據(jù)類型、長度等等,需使用游標(biāo)或者更加準(zhǔn)確的說,使用sql語句進(jìn)行訪問才行。慶幸的是制作arcpy代碼庫或者函數(shù)庫的編寫者們會考慮到單個函數(shù)使用的通用性,即便是不同的數(shù)據(jù)類型也希望封裝成一個函數(shù)進(jìn)行訪問,我們在外部幾乎看不出數(shù)據(jù)類型的不同導(dǎo)致的訪問函數(shù)不一樣。
arcgis將各類數(shù)據(jù)看作是數(shù)據(jù)集,無論是矢量的、柵格的、數(shù)據(jù)庫、抑或是文件型的(文件夾)。其訪問方式全部封裝在列表函數(shù)中---list()。列表系列的函數(shù)有:
ListFiles--文件列表、
ListWorkspaces--工作空間列表、
ListDatasets--數(shù)據(jù)集列表、
ListFeatureClasses--要素類列表、
ListRasters--柵格列表、
ListTables--屬性表列表等等。
只要事先設(shè)置工作空間,即可將所有數(shù)據(jù)讀入列表中,而如果再配合arcpy的工具函數(shù)和循環(huán)語句,即可做大量的批處理工作。
import arcpy
from arcpy import env
env.workspace="c:/data"??
imgs=arcpy.ListRasters("","img")
for img in imgs:
? arcpy.BuildPyramids_management(img)
以上代碼就是為“data”文件夾下的所有img柵格數(shù)據(jù)創(chuàng)建金字塔。
使用列表函數(shù)可以輕松地將數(shù)據(jù)直接導(dǎo)入內(nèi)存中,進(jìn)而交給工具函數(shù)處理。
差異性訪問
矢量數(shù)據(jù)中,最出名的莫過于shapefile 文件了,其表現(xiàn)方式為:
- .shp - 存儲要素幾何的主文件;必需文件。
- .shx - 存儲要素幾何索引的索引文件;必需文件。
- .dbf - 存儲要素屬性信息的 dBASE 表;必需文件。
- .prj - 存儲坐標(biāo)系信息的文件;由 ArcGIS 使用。
- .xml - ArcGIS 的元數(shù)據(jù) - 用于存儲 shapefile 的相關(guān)信息。
- .sbn 和 .sbx - 存儲要素空間索引的文件。
- .fbn 和 .fbx - 存儲只讀 shapefile 的要素空間索引的文件。
- .ain 和 .aih - 存儲某個表中或?qū)n}屬性表中活動字段屬性索引的文件。
- .atx - .atx 文件針對各個 shapefile 或在 ArcCatalog 中創(chuàng)建的 dBASE屬性索引而創(chuàng)建。
- .ixs - 讀/寫 shapefile 的地理編碼索引。
- .mxs - 讀/寫 shapefile(ODB 格式)的地理編碼索引。
- .cpg - 可選文件,指定用于標(biāo)識要使用的字符集的代碼頁。
從以上也可以看出,矢量數(shù)據(jù)有幾個基本組成部分:1、幾何要素、2、屬性表、3、空間坐標(biāo)信息、4、地理編碼。
在其他矢量格式數(shù)據(jù)中都需要這四類信息,幾何要素用以表示圖形,屬性表用以表示屬性信息,空間坐標(biāo)信息用以表示該矢量數(shù)據(jù)存在于那類空間坐標(biāo)中,地理編碼用于幾何要素的空間定位。
因此,圍繞矢量數(shù)據(jù)的訪問,也就有著不同的訪問方式,或以幾何對象訪問(幾何圖形),或以游標(biāo)訪問(屬性表),或以幾何對象的封裝屬性訪問(空間坐標(biāo)信息、地理編碼),相對而言,矢量數(shù)據(jù)的訪問方式較為復(fù)雜。
(這里我們不討論矢量點、線、面的不同幾何類型)
柵格數(shù)據(jù)中,img表現(xiàn)方式為:
? ? ?img:索引文件,?
? ? ?rrd:金字塔文件,?
? ? ?ige:柵格數(shù)據(jù)。?
? ? ?rde:在某些情況下,金字塔文件(rrd)也會超過2GB,這時會創(chuàng)建rde文件來存儲這些信息
其中img文件像其他圖像格式的文件(如:bmp,tiff,hdf等)一樣,存有圖像一些文件頭信息,如:圖像的大小、波段、行列數(shù),分辨率、是否壓縮、像素的行列數(shù)、位深等,還有空間坐標(biāo)信息等,其基本組成部分有:1、柵格信息(R、G、B、NIR等)2空間坐標(biāo)信息、3、波段、行列數(shù)、分辨率、位深
因此,柵格數(shù)據(jù)的訪問一般只是訪問柵格信息,其他的基本很少過問,雖然波段、行列數(shù)、分辨率、位深如此多的信息,但是它們都是相對單一的。
arcpy在解決以上的差異性問題時,提供的工具有:使用游標(biāo)訪問矢量數(shù)據(jù)單個屬性項數(shù)據(jù),使用numpy數(shù)組遍歷柵格數(shù)據(jù)單個柵格值。
矢量屬性訪問
游標(biāo)是包含從要素類或表中獲取的一行或多行數(shù)據(jù)的內(nèi)存對象。每行數(shù)據(jù)包含了數(shù)據(jù)源中每個字段中的屬性以及每個要素的幾何信息。游標(biāo)可對表和要素類的數(shù)據(jù)進(jìn)行搜索,增加,插入,更新以及刪除。arcpy.da提供了三個游標(biāo)函數(shù)。
| SearchCursor() | SearchCursor | 只讀查看表或要素類數(shù)據(jù) |
| InsertCursor() | InsertCursor | 向表或要素類插入行 |
| UpdateCursor() | UpdateCursor | 編輯或刪除表和要素類行 |
SearchCursor():用于在要素類或表上建立只讀游標(biāo)。SearchCursor?可用于遍歷?Row?對象并提取字段值。可以使用 where 子句或字段限制搜索,并對結(jié)果排序。
語法
SearchCursor (dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields})| 參數(shù) | 說明 | 數(shù)據(jù)類型 |
| dataset | 包含要搜索行的要素類、shapefile 或表。 | String |
| where_clause | 用于限制在游標(biāo)中返回的行的可選表達(dá)式。有關(guān) where 子句和 SQL 語句的詳細(xì)信息,請參閱?構(gòu)建 SQL 查詢。 | String |
| spatial_reference | 指定后,要素將使用提供的?spatial_reference?進(jìn)行動態(tài)投影。 | SpatialReference |
| fields | 游標(biāo)中包含以分號分隔的字符串字段。默認(rèn)情況下,包含所有字段。 | String |
| sort_fields | 用于在游標(biāo)中對行進(jìn)行排序的字段。每個字段的升序和降序排列表示為?"field1 A;field2 B"?形式,A?表示升序,D?表示降序。 | String |
返回值
| 數(shù)據(jù)類型 | 說明 |
| Cursor | 可分發(fā)?Row?對象的?Cursor?對象。 |
列出 Counties.shp 的字段內(nèi)容。游標(biāo)按州名稱和人口進(jìn)行排序。
import arcpy # Open a searchcursor # Input: C:/Data/Counties.shp # Fields: NAME; STATE_NAME; POP2000 # Sort fields: STATE_NAME A; POP2000 D rows = arcpy.SearchCursor("c:/data/counties.shp",fields="NAME; STATE_NAME; POP2000",sort_fields="STATE_NAME A; POP2000 D") # Iterate through the rows in the cursor and print out the # state name, county and population of each. for row in rows:print("State: {0}, County: {1}, Population: {2}".format(row.getValue("STATE_NAME"),row.getValue("NAME"),row.getValue("POP2000")))InsertCursor():向要素類、shapefile 或表中插入行。InsertCursor?可返回一個分發(fā)?Row?對象的枚舉對象。
語法
InsertCursor (dataset, {spatial_reference})| 參數(shù) | 說明 | 數(shù)據(jù)類型 |
| dataset | 將向其中插入行的表、要素類或 shapefile。 | String |
| spatial_reference | 在提供的?spatial_reference?中指定的坐標(biāo),并動態(tài)轉(zhuǎn)換到數(shù)據(jù)集的坐標(biāo)系。 | SpatialReference |
返回值
| 數(shù)據(jù)類型 | 說明 |
| Cursor | 返回針對指定要素類、shapefile 或表的?Cursor?對象。 |
向表中插入 25 個新行。
import arcpy # Create insert cursor for table rows = arcpy.InsertCursor("c:/base/data.gdb/roads_lut") # Create 25 new rows. Set the initial row ID and distance values for x in range(1, 26):row = rows.newRow()row.setValue("rowid", x)row.setValue("distance", 100)rows.insertRow(row) # Delete cursor and row objects to remove locks on the data del row del rowsUpdateCursor():創(chuàng)建一個用于更新或刪除指定要素類、shapefile 和表中的行的游標(biāo)。該游標(biāo)將數(shù)據(jù)鎖定保留至腳本完成或更新游標(biāo)對象被刪除時。
語法
UpdateCursor (dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields})| 參數(shù) | 說明 | 數(shù)據(jù)類型 |
| dataset | 包含要更新或刪除行的要素類、shapefile 或表。 | String |
| where_clause | 用于限制在游標(biāo)中返回的行的可選表達(dá)式。有關(guān) where 子句和 SQL 語句的詳細(xì)信息,請參閱在查詢表達(dá)式中使用的元素的 SQL 參考。 | String |
| spatial_reference | 在提供的?spatial_reference?中指定的坐標(biāo),并動態(tài)轉(zhuǎn)換到數(shù)據(jù)集的坐標(biāo)系。 | SpatialReference |
| fields | 游標(biāo)中包含以分號分隔的字符串字段。默認(rèn)情況下,包含所有字段。 | String |
| sort_fields | 用于在游標(biāo)中對行進(jìn)行排序的字段。每個字段的升序和降序排列表示為?"field1 A;field2 B"?形式,A?表示升序,D?表示降序。 | String |
返回值
| 數(shù)據(jù)類型 | 說明 |
| Cursor | 可分布?Row?對象的?Cursor?對象。 |
根據(jù)另一個字段值更新要素類中的字段值。
import arcpy # Create update cursor for feature class rows = arcpy.UpdateCursor("c:/data/base.gdb/roads") # Update the field used in buffer so the distance is based on the # road type. Road type is either 1, 2, 3, or 4. Distance is in meters. for row in rows:# Fields from the table can be dynamically accessed from the# row object. Here fields named BUFFER_DISTANCE and ROAD_TYPE# are usedrow.setValue("BUFFER_DISTANCE", row.getValue("ROAD_TYPE") * 100)rows.updateRow(row) # Delete cursor and row objects to remove locks on the data. del row del rows以上三個游標(biāo)函數(shù)都返回一個游標(biāo)對象,游標(biāo)對象根據(jù)實際對象的改變而改變。
矢量幾何訪問
空間數(shù)據(jù)需要同時維護(hù)屬性表數(shù)據(jù)與圖形數(shù)據(jù)信息,圖形數(shù)據(jù)和屬性數(shù)據(jù)之間通過唯一的ID號進(jìn)行對象內(nèi)部關(guān)聯(lián),涉及到空間數(shù)據(jù)更新時,一般是同時更新空間對象的屬性數(shù)據(jù)和圖形數(shù)據(jù)。空間圖形對象定義了空間圖形的空間位置、形狀,空間圖形包含點、多點、線、面、多面體等多種空間圖形對象,空間圖形對象是空間拓?fù)洹⒖臻g分析、空間幾何網(wǎng)絡(luò)構(gòu)造的基礎(chǔ),在創(chuàng)建空間幾何對象的時候,空間邊界、最小邊界多邊形、包含、相交、接觸、相離、合并等空間關(guān)系等對象或者方法得以繼承,可以直接使用空間圖形對象更新圖形信息,又因Arcpy調(diào)用了arcobject空間對象的方法,也可以使用圖形令牌訪問圖形信息,同時也可以使用游標(biāo)方式對屬性數(shù)據(jù)和圖形數(shù)據(jù)進(jìn)行同步更新。如果只需要圖形的某些特定屬性,利用圖形令牌訪問幾何屬性即可,操作比圖形對象訪問更加簡便,例如:SHAPE@XY 會返回一組代表要素質(zhì)心的 x,y 坐標(biāo)。
| SHAPE@ | 要素的幾何對象。 |
| SHAPE@XY | 一組要素的質(zhì)心 x,y 坐標(biāo)。 |
| SHAPE@TRUECENTROID | 一組要素的真正質(zhì)心 x,y 坐標(biāo)。 |
| SHAPE@X | 要素的雙精度 x 坐標(biāo)。 |
| SHAPE@Y | 要素的雙精度 y 坐標(biāo)。 |
| SHAPE@Z | 要素的雙精度 z 坐標(biāo)。 |
| SHAPE@M | 要素的雙精度 m 值。 |
| SHAPE@JSON | 表示幾何的 esri JSON 字符串。 |
| SHAPE@WKB | OGC 幾何的熟知二進(jìn)制 (WKB) 制圖表達(dá)。該存儲類型將幾何值表示為不間斷的字節(jié)流形式。 |
| SHAPE@WKT | OGC 幾何的熟知文本 (WKT) 制圖表達(dá)。其將幾何值表示為文本字符串。 |
| SHAPE@AREA | 要素的雙精度面積。 |
| SHAPE@LENGTH | 要素的雙精度長度。 |
使用幾何對象
import arcpy
feature_info = [[[1, 2], [2, 4], [3, 7]],
? ? ? ? ? ? ? ? [[6, 8], [5, 7], [7, 2], [9, 5]]]
features = []
for feature in feature_info:
? ? features.append(
? ? ? ? arcpy.Polygon(
? ? ? ? ? ? arcpy.Array([arcpy.Point(*coords) for coords in feature])))
arcpy.CopyFeatures_management(features, "c:/geometry/polygons.shp")
使用圖形令牌
import arcpy
feature_class = "c:/data/Hawaii.shp"cursor = arcpy.da.SearchCursor(feature_class, ["SHAPE@"])
for row in cursor:
? ? print("Number of Hawaiian islands: {0}".format(row[0].partCount))
? ? for island in row[0].getPart():
? ? ? ? print("Vertices in island: {0}".format(island.count))
? ? ? ? for point in island:
? ? ? ? ? ? print("X: {0}, Y: {1})".format(point.X, point.Y))
幾何數(shù)據(jù)、屬性數(shù)據(jù)一起插入
import arcpy
row_values = [('Anderson', (1409934.4442000017, 1076766.8192000017)),
? ? ? ? ? ? ? ('Andrews', (752000.2489000037, 1128929.8114))]
cursor = arcpy.da.InsertCursor("C:/data/texas.gdb/counties",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?("NAME", "SHAPE@XY"))
for row in row_values:
? ? cursor.insertRow(row)
del cursor
柵格數(shù)據(jù)訪問
import arcpy
arcpy.raster()
NumPy 數(shù)組是包含在 Python 的 SciPy 科學(xué)計算包中的最著名數(shù)組,很多現(xiàn)有 Python 函數(shù)都是為了處理 NumPy 數(shù)組而創(chuàng)建。
柵格可以使用 ArcPy 函數(shù)?RasterToNumPyArray?和?NumPyArrayToRaster?轉(zhuǎn)換為 NumPy 數(shù)組,也可以使用同樣的函數(shù)從這些數(shù)組反向轉(zhuǎn)換。您可能想要將 ArcGIS 柵格轉(zhuǎn)換為 NumPy 數(shù)組以:
用于處理柵格的 arcpy 函數(shù)
| RasterToNumPyArray | 將柵格轉(zhuǎn)換為 NumPy 數(shù)組。 |
| NumPyArrayToRaster | 將 NumPy 數(shù)組轉(zhuǎn)換為柵格。 |
語法
RasterToNumPyArray (in_raster, {lower_left_corner}, {ncols}, {nrows}, {nodata_to_value})| 參數(shù) | 說明 | 數(shù)據(jù)類型 |
| in_raster | 要轉(zhuǎn)換為 NumPy 數(shù)組的輸入柵格。 | Raster |
| lower_left_corner | 可從?in_raster?中的左下角提取處理塊以轉(zhuǎn)換為數(shù)組。x 值和 y 值采用地圖單位。若未指定值,則將使用輸入柵格的原點。 (默認(rèn)值為 None) | Point |
| ncols | in_raster?中要轉(zhuǎn)換為 NumPy 數(shù)組的?lower_left_corner?中的列數(shù)。 若未指定值,則將使用輸入柵格的列數(shù)。 (默認(rèn)值為 None) | Integer |
| nrows | in_raster?中要轉(zhuǎn)換為 NumPy 數(shù)組的?lower_left_corner?中的行數(shù)。 若未指定值,則將使用輸入柵格的行數(shù)。 (默認(rèn)值為 None) | Integer |
| nodata_to_value | 在生成的 NumPy 數(shù)組中分配?in_raster?NoData 值的值。 若未指定值,則將使用?in_raster?的 NoData 值。 (默認(rèn)值為 None) | Variant |
將柵格數(shù)據(jù)轉(zhuǎn)換為 NumPy 數(shù)組旨在計算整個柵格行中的像元值的百分比。然后,將會創(chuàng)建一個新的柵格數(shù)據(jù)。
import arcpy import numpy my_array = arcpy.RasterToNumPyArray('C:/data/inRaster') my_array_sum = my_array.sum(1) my_array_sum.shape = (my_array.shape[0], 1) my_array_perc = (my_array * 1.0) / my_array_sum new_raster = arcpy.NumPyArrayToRaster(my_array_perc) new_raster.save("C:/output/fgdb.gdb/PercentRaster")只要將柵格數(shù)據(jù)轉(zhuǎn)換成為NumPy矩陣數(shù)組,那么遙感影像的分割、分類、聚類、機(jī)器學(xué)習(xí)等都將成為可能。它內(nèi)置有很多數(shù)學(xué)運算函數(shù),支持大量高級的維度數(shù)組與矩陣運算,是大量機(jī)器學(xué)習(xí)框架的基礎(chǔ)庫。它通常與SciPy一起用于科學(xué)計算,某種程度上可以取代matlab。
SciPy模塊組成:
| scipy.cluster | 矢量量化 / K-均值 |
| scipy.constants | 物理和數(shù)學(xué)常數(shù) |
| scipy.fftpack | 傅里葉變換 |
| scipy.integrate | 積分程序 |
| scipy.interpolate | 插值 |
| scipy.io | 數(shù)據(jù)輸入輸出 |
| scipy.linalg | 線性代數(shù)程序 |
| scipy.ndimage | n維圖像包 |
| scipy.odr | 正交距離回歸 |
| scipy.optimize | 優(yōu)化 |
| scipy.signal | 信號處理 |
| scipy.sparse | 稀疏矩陣 |
| scipy.spatial | 空間數(shù)據(jù)結(jié)構(gòu)和算法 |
| scipy.special | 任何特殊數(shù)學(xué)函數(shù) |
| scipy.stats | 統(tǒng)計 |
元數(shù)據(jù)訪問(或者說描述性數(shù)據(jù)訪問)
地理信息數(shù)據(jù)類型多種多樣,每種數(shù)據(jù)類型都有特定的屬性,在實際使用過程中常常需要事先知道這些信息。arcpy中的describe函數(shù)就可以很好的實現(xiàn)這一點。describe函數(shù)可以識別很多數(shù)據(jù)集的類型,包括、要素類、要素數(shù)據(jù)集、數(shù)據(jù)庫、柵格數(shù)據(jù)、柵格數(shù)據(jù)集、鑲嵌數(shù)據(jù)集等等,同時,它返回一個多屬性的describe對象,這個describe對象是動態(tài)的,它隨著輸入對象的改變而改變。
語法
Describe (value, {datatype})| 參數(shù) | 說明 | 數(shù)據(jù)類型 |
| value | 要描述的指定數(shù)據(jù)元素或地理處理對象。 | String |
| datatype | 數(shù)據(jù)的類型。僅當(dāng)存在命名沖突(例如,如果地理數(shù)據(jù)庫包含同名的要素數(shù)據(jù)集 (FeatureDataset) 和要素類 (FeatureClass))時需要此項。在這種情況下,數(shù)據(jù)類型將用于確定要描述的數(shù)據(jù)集。 (默認(rèn)值為 None) | String |
返回值
| 數(shù)據(jù)類型 | 說明 |
| Describe | 返回的對象屬性中包含被描述對象的詳細(xì)信息。某些返回的對象屬性會包含文本值或?qū)ο蟆?/p> |
Describe?對象屬性
| 屬性 | 說明 | 數(shù)據(jù)類型 |
| baseName (只讀) | 文件基本名稱 | String |
| catalogPath (只讀) | 數(shù)據(jù)路徑 | String |
| children (只讀) | 子元素列表 | Describe |
| childrenExpanded (只讀) | 指示子元素是否已擴(kuò)展 | Boolean |
| dataElementType (只讀) | 元素的元素類型 | String |
| dataType (只讀) | 元素類型 | String |
| extension (只讀) | 文件擴(kuò)展名 | String |
| file (只讀) | 文件名稱 | String |
| fullPropsRetrieved (只讀) | 指示是否已檢索完整屬性 | Boolean |
| metadataRetrieved (只讀) | 指示是否已檢索元數(shù)據(jù) | Boolean |
| name (只讀) | 元素的用戶分配名稱 | String |
| path (只讀) | 文件路徑 | String |
常見數(shù)據(jù)類型子Describe對象屬性有:
要素類屬性
| 屬性 | 說明 | 數(shù)據(jù)類型 |
| featureType (只讀) | 要素類的要素類型。
| String |
| hasM (只讀) | 指示幾何是否啟用 m 值。 | Boolean |
| hasZ (只讀) | 指示幾何是否啟用 z 值。 | Boolean |
| hasSpatialIndex (只讀) | 指示要素類是否具有空間索引。 | Boolean |
| shapeFieldName (只讀) | Shape 字段的名稱。 | String |
| shapeType (只讀) | 幾何形狀類型。
| String |
柵格數(shù)據(jù)集屬性
| 屬性 | 說明 | 數(shù)據(jù)類型 |
| bandCount (只讀) | 柵格數(shù)據(jù)集內(nèi)的波段數(shù)。 | Integer |
| compressionType (只讀) | 壓縮類型
| String |
| format (只讀) | 柵格格式
| String |
| permanent (只讀) | 指示柵格的永久狀態(tài):False 表示臨時柵格;True 表示永久柵格。 | Boolean |
| sensorType (只讀) | 用于捕獲圖像的傳感器類型。 | String |
表屬性
| 屬性 | 說明 | 數(shù)據(jù)類型 |
| hasOID (只讀) | 指示表是否包含 ObjectID 字段。 | Boolean |
| OIDFieldName (只讀) | OID 字段(如果存在)名稱。 | String |
| fields (只讀) | 此表的字段對象的 Python 列表。這與使用?ListFields?函數(shù)時相同。 | Field |
| indexes (只讀) | 此表的索引對象的 Python 列表。這與使用?ListIndexes?函數(shù)時相同。 | Index |
其他對象屬性情況可參看describe函數(shù):Describe—ArcGIS Pro | 文檔?
二、制作腳本工具
地理處理:制作地理處理工具
地理處理:制作地理處理模型
三、發(fā)布地理處理服務(wù)
地理處理:共享地理處理服務(wù)
不知這個需要寫多久,估計也是像以前那篇關(guān)于坐標(biāo)系的文章一樣,斷斷續(xù)續(xù)需要個三年五載的。
附件:
argis中自帶python其他站點包使用
1、將python和pip執(zhí)行程序的路徑添加進(jìn)系統(tǒng)配置路徑
檢查argis中的python和pip是否可用
2、pip安裝
? ? ?pypi是Python編程語言的軟件存儲庫,PyPI可幫助您查找和安裝Python社區(qū)開發(fā)和共享的軟件。pip用于搜索、下載、管理、卸載PyPI上的Python包。
PyPI · The Python Package Index
搜索pip
也可以直接以鏈接官網(wǎng)下載pip包,地址是pip · PyPI
? ? ? 下載完成之后,解壓到一個文件夾,用cmd進(jìn)入這個解壓好的文件夾,輸入:Python?setup.py install?
? ?
?再次檢查站點是否可用,cmd中輸入:pip
3 因國外站點pypi速度較慢,使用國內(nèi)pypi鏡像站點
站點如下:
阿里云 http://mirrors.aliyun.com/pypi/simple
中國科學(xué)技術(shù)大學(xué) http://pypi.mirrors.ustc.edu.cn/simple
中國科技大學(xué) https://pypi.mirrors.ustc.edu.cn/simple
豆瓣(douban) http://pypi.douban.com/simple
清華大學(xué) https://pypi.tuna.tsinghua.edu.cn/simple
使用方法:
在pip下,執(zhí)行以下命令,如下載request包
pip install request -i https://pypi.tuna.tsinghua.edu.cn/simple
會發(fā)現(xiàn),網(wǎng)速果然比一起啊快了好多?
如果出現(xiàn)這是未信任的源,修改上述命令,如下:
pip install request -i https://pypi.tuna.tsinghua.edu.cn/simple?
- -trusted-host pypi.tuna.tsinghua.edu.cn
如果想使用其為默認(rèn)源?
windows下可修改%HOMEPATH%\pip\pip.ini文件?
修改內(nèi)容為:?
[global]?
index-url = https://pypi.tuna.tsinghua.edu.cn/simple?
[install]?
trusted-host=pypi.tuna.tsinghua.edu.cn
?
easy_install的安裝:
1 在命令提示符或終端程序中執(zhí)行“easy_install --version”檢驗在當(dāng)前操作系統(tǒng)是否安裝了easy_install.
C:\Users\liangxiang>easy_install --version
setuptools 28.8.0 from e:\python\lib\site-packages (Python 3.5)
2 若無前往https://pypi.python.org/pypi/ez_setup下載一個名叫ez_setup.py的程序。解壓安裝,方法:cmd進(jìn)入到對應(yīng)目錄下(我的下載目錄為E:\python\Lib\ez_setup-0.9),
執(zhí)行命令:python ez_setup.py
C:\Users\liangxiang>e
?
E:\>cd E:\python\Lib\ez_setup-0.9
?
E:\python\Lib\ez_setup-0.9>python ez_setup.py
easy_install的用法:
1.0 通過庫名安裝(默認(rèn)情況下安裝最新版本)
easy_install 軟件包名稱
2.0安裝指定版本
easy_install '軟件包的名稱==版本號'
3.0不指定版本號,要求某一個版本之前或之后的版本
easy_install '軟件包名稱<=版本號'
4.0安裝已經(jīng)下載的egg文件
easy_install /文件下載路徑/egg文件名
5.0安裝包卸載
easy_install -m 軟件包名稱
?6.0安裝包更新
#默認(rèn)最新版本
easy_install --upgrade 安裝包名稱?
easy_install -U 安裝包名稱 ? ? ??
#指定升級的版本
easy_install " 安裝包名稱==版本號"
easy_install " 安裝包名稱>版本號"
pip的安裝:
1 若已經(jīng)安裝easy_install,直接用命令安裝
easy_install install pip
2 若無,前往https://pypi.python.org/pypi/pip?下載pip-18.0.tar.gz?文件,解壓下載的文件,進(jìn)入解壓后的文件夾中,調(diào)出命令行窗口或者終端,輸入 python setup.py install
python setup.py install
3 檢驗pip是否安裝成功
C:\Users\liangxiang>pip --version
pip 18.0 from e:\python\lib\site-packages\pip-18.0-py3.5.egg\pip (python 3.5)
?
pip的用法:
1.0??通過庫名安裝
pip install 軟件包名稱
2.0?安裝指定版本
pip install "軟件包名稱==版號"
3.0?不指定版本號,要求某一個版本之前或之后的版本
pip install "軟件包名稱>=版號"
4.0軟件包卸載
pip uninstall 軟件包名稱
5.0??列出所有安裝的庫
pip list ?
pip freeze?
6.0?列出所有過期的庫
pip list --outdated?
7.0 庫更新
pip install --upgrade 庫名?
?
pip install -U 庫名
8.0 過期庫批量更新/安裝
pip freeze > xxxx.txt #導(dǎo)出當(dāng)前系統(tǒng)安裝的庫,保存為TXT文件
( pip freeze > E:\\XXX.txt #保存到指定文件夾 )
pip install -r xxxx.txt
9.0 查詢某一個庫的相關(guān)信息
pip search 庫名
10.0 其他高級功能,用help查詢
pip help
?
寄語
很多時候我們對arcpy是望而卻步的,不僅僅是因為它需要編碼,而是我們對于地理信息很多本身的邏輯思維都不甚了解。比如,你可能聽說過空間統(tǒng)計分析,但是你是否知道自相關(guān)系數(shù)、歐式距離、線性/非線性回歸、聚類等知識,我們的回答常常是否定的。大凡一類事物都有他獨有的規(guī)則和范圍體系,當(dāng)我們說到一類編程語言的時候,就勢必涉及語法規(guī)則、數(shù)據(jù)類型、控制結(jié)構(gòu)、編寫環(huán)境,編譯工具等等,當(dāng)編程語言觸及web網(wǎng)絡(luò)時,也勢必涉及網(wǎng)絡(luò)七層協(xié)議、數(shù)據(jù)交換、https、css、端口號等等,當(dāng)我們談到地圖服務(wù)的時候,又會涉及到網(wǎng)絡(luò)地址、服務(wù)類型、坐標(biāo)體系、分辨率、比例尺、旋轉(zhuǎn)參數(shù)等等。arcpy也同樣有它的規(guī)則和體系,它屬于python的,必須符合python規(guī)則,它又是屬于arcgis的,它也必須符合arcgis甚至于地理信息的一些規(guī)則。掌握這些規(guī)則的過程,也是提升我們自身的過程。
總結(jié)
- 上一篇: IO流复制图片
- 下一篇: c语言从入门到精通第四版电子书_C语言从