Python实现点shp文件读取并转换成geojson
不调用shapefile库的一种写法~
import os
import struct
class GISPoints(object):
def __init__(self,x,y,att=None):
self.x=x
self.y=y
self.att=att
def __str__(self):
return "E"
class GISShapefile(object):
def __init__(self):
# 无效字段
self.Unused=[None for i in range(7)]
# 版本
self.verson=None
# 类型
self.ShapeType=None
self.ShapeName="None"
# 范围
self.GeoRange=[None for i in range(4)]
# 三维
self.Unused1=[None for i in range(4)]
# 所有点
self.Points=[]
def ReadPoint(self,by:bytes)->object:
x,y=struct.unpack('d',by[:8])[0],struct.unpack('d',by[8:16])[0]
return GISPoints(x,y)
def ReadFileHead(self,shapename=None):
if not shapename:
raise Exception("None FilePath")
if not os.path.exists(shapename):
raise Exception("Error Path")
file,ext=os.path.splitext(shapename)
self.ShapeName=file.split("\\")[-1]+ext
try:
f=open("%s%s"%(file,ext),"rb")
self.ReadShpaeHeader(f)
try:
while True:
self.ReadRecordHeader(f)
except:
pass
finally:
f.close()
except IOError:
try:
f = open("%s%s" % (file, ext.upper()), "rb")
self.ReadShpaeHeader(f)
try:
while True:
self.ReadRecordHeader(f)
except:
pass
finally:
f.close()
except IOError:
pass
def ReadShpaeHeader(self,f):
for _ in range(7):
self.Unused[_]=struct.unpack("i",f.read(4))[0]
self.verson=struct.unpack("i",f.read(4))[0]
self.ShapeType=struct.unpack("i",f.read(4))[0]
for _ in range(4):
self.GeoRange[_]=struct.unpack("d",f.read(8))[0]
for _ in range(4):
self.Unused1[_]=struct.unpack("d",f.read(8))[0]
def __str__(self):
print("Verson: ",self.verson)
print("ShapeTyep: ",self.__map__(self.ShapeType))
print("Xmin:%f,Ymin:%f,Xmax:%f,Ymax:%f"%(self.GeoRange[0],self.GeoRange[1],
self.GeoRange[2],self.GeoRange[3]))
print("Points: ",len(self.Points))
return self.ShapeName
def __map__(self,a:int)->str:
if a==1:
return "Point"
elif a==3:
return "Line"
elif a==5:
return "Polygon"
else:
return "UNKNOWN"
def ReadRecordHeader(self,f):
tem=[0 for i in range(3)] # 记录数量 记录长度 空间类型
for i in range(3):
a=self.change(f.read(4))
tem[i]=int.from_bytes(a,byteorder="little",signed=False)
Recordlenth=tem[1]*2-4
byte_content=f.read(Recordlenth)
newpoints=self.ReadPoint(byte_content)
byte_content=byte_content[16:]
self.Points.append(newpoints)
return self.Points
def change(self,by):
return by[::-1]
def sequencing(self,path):
size=len(self.Points)
if size==0:
raise Exception("No Points!")
elif size==1:
Type='"Point"'
else:
Type='"MultiPoint"'
with open(path,"w") as f:
f.write('"geometry":{'+"\n")
f.write(' "type":%s'%Type+","+"\n")
Coordinates=[]
for i in self.Points:
Coordinates.append([i.x,i.y])
f.write(' "coordinates":'+str(Coordinates)+"\n")
f.write("}")
te=GISShapefile()
te.ReadFileHead(r"\Desktop\云南县城.shp")
te.sequencing(r"\Desktop\云南县城.geojson")
print(te)
结果与shapefile库读取的一致(磕了半天shapefile库源码,别问我为什么不用,问就是老师把写好的第三方库ban了)