Skip to content

Commit d67c8fc

Browse files
authored
Merge pull request #92 from GeospatialPython/karimbahgat-patch-recordlengthfix
Read correct length of record in case of bad file
2 parents 7031a47 + 6774ad0 commit d67c8fc

File tree

1 file changed

+13
-15
lines changed

1 file changed

+13
-15
lines changed

shapefile.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -444,23 +444,16 @@ def iterShapes(self):
444444
while shp.tell() < self.shpLength:
445445
yield self.__shape()
446446

447-
def __dbfHeaderLength(self):
448-
"""Retrieves the header length of a dbf file header."""
449-
if not self.__dbfHdrLength:
450-
if not self.dbf:
451-
raise ShapefileException("Shapefile Reader requires a shapefile or file-like object. (no dbf file found)")
452-
dbf = self.dbf
453-
(self.numRecords, self.__dbfHdrLength) = \
454-
unpack("<xxxxLH22x", dbf.read(32))
455-
return self.__dbfHdrLength
456-
457447
def __dbfHeader(self):
458448
"""Reads a dbf header. Xbase-related code borrows heavily from ActiveState Python Cookbook Recipe 362715 by Raymond Hettinger"""
459449
if not self.dbf:
460450
raise ShapefileException("Shapefile Reader requires a shapefile or file-like object. (no dbf file found)")
461451
dbf = self.dbf
462-
headerLength = self.__dbfHeaderLength()
463-
numFields = (headerLength - 33) // 32
452+
# read relevant header parts
453+
self.numRecords, self.__dbfHdrLength, self.__recordLength = \
454+
unpack("<xxxxLHH20x", dbf.read(32))
455+
# read fields
456+
numFields = (self.__dbfHdrLength - 33) // 32
464457
for field in range(numFields):
465458
fieldDesc = list(unpack("<11sc4xBB14x", dbf.read(32)))
466459
name = 0
@@ -487,6 +480,11 @@ def __recordFmt(self):
487480
self.__dbfHeader()
488481
fmt = ''.join(['%ds' % fieldinfo[2] for fieldinfo in self.fields])
489482
fmtSize = calcsize(fmt)
483+
# total size of fields should add up to recordlength from the header
484+
while fmtSize < self.__recordLength:
485+
# if not, pad byte until reaches recordlength
486+
fmt += "x"
487+
fmtSize += 1
490488
return (fmt, fmtSize)
491489

492490
def __record(self):
@@ -554,7 +552,7 @@ def record(self, i=0):
554552
i = self.__restrictIndex(i)
555553
recSize = self.__recStruct.size
556554
f.seek(0)
557-
f.seek(self.__dbfHeaderLength() + (i * recSize))
555+
f.seek(self.__dbfHdrLength + (i * recSize))
558556
return self.__record()
559557

560558
def records(self):
@@ -563,7 +561,7 @@ def records(self):
563561
self.__dbfHeader()
564562
records = []
565563
f = self.__getFileObj(self.dbf)
566-
f.seek(self.__dbfHeaderLength())
564+
f.seek(self.__dbfHdrLength)
567565
for i in range(self.numRecords):
568566
r = self.__record()
569567
if r:
@@ -576,7 +574,7 @@ def iterRecords(self):
576574
if self.numRecords is None:
577575
self.__dbfHeader()
578576
f = self.__getFileObj(self.dbf)
579-
f.seek(self.__dbfHeaderLength())
577+
f.seek(self.__dbfHdrLength)
580578
for i in xrange(self.numRecords):
581579
r = self.__record()
582580
if r:

0 commit comments

Comments
 (0)