10
10
11
11
__version__ = "1.2.3"
12
12
13
- from struct import pack , unpack , calcsize , error
13
+ from struct import pack , unpack , calcsize , error , Struct
14
14
import os
15
15
import sys
16
16
import time
@@ -346,7 +346,8 @@ def __shape(self):
346
346
record .partTypes = _Array ('i' , unpack ("<%si" % nParts , f .read (nParts * 4 )))
347
347
# Read points - produces a list of [x,y] values
348
348
if nPoints :
349
- record .points = [_Array ('d' , unpack ("<2d" , f .read (16 ))) for p in range (nPoints )]
349
+ flat = unpack ("<%sd" % (2 * nPoints ), f .read (16 * nPoints ))
350
+ record .points = list (izip (* (iter (flat ),) * 2 ))
350
351
# Read z extremes and values
351
352
if shapeType in (13 ,15 ,18 ,31 ):
352
353
(zmin , zmax ) = unpack ("<2d" , f .read (16 ))
@@ -389,10 +390,12 @@ def __shapeIndex(self, i=None):
389
390
numRecords = shxRecordLength // 8
390
391
# Jump to the first record.
391
392
shx .seek (100 )
392
- for r in range (numRecords ):
393
- # Offsets are 16-bit words just like the file length
394
- self ._offsets .append (unpack (">i" , shx .read (4 ))[0 ] * 2 )
395
- shx .seek (shx .tell () + 4 )
393
+ shxRecords = _Array ('i' )
394
+ # Each offset consists of two nrs, only the first one matters
395
+ shxRecords .fromfile (shx , 2 * numRecords )
396
+ if sys .byteorder != 'big' :
397
+ shxRecords .byteswap ()
398
+ self ._offsets = [2 * el for el in shxRecords [::2 ]]
396
399
if not i == None :
397
400
return self ._offsets [i ]
398
401
@@ -469,6 +472,8 @@ def __dbfHeader(self):
469
472
if terminator != b ("\r " ):
470
473
raise ShapefileException ("Shapefile dbf header lacks expected terminator. (likely corrupt?)" )
471
474
self .fields .insert (0 , ('DeletionFlag' , 'C' , 1 , 0 ))
475
+ fmt ,fmtSize = self .__recordFmt ()
476
+ self .__recStruct = Struct (fmt )
472
477
473
478
def __recordFmt (self ):
474
479
"""Calculates the size of a .shp geometry record."""
@@ -481,8 +486,7 @@ def __recordFmt(self):
481
486
def __record (self ):
482
487
"""Reads and returns a dbf record row as a list of values."""
483
488
f = self .__getFileObj (self .dbf )
484
- recFmt = self .__recordFmt ()
485
- recordContents = unpack (recFmt [0 ], f .read (recFmt [1 ]))
489
+ recordContents = self .__recStruct .unpack (f .read (self .__recStruct .size ))
486
490
if recordContents [0 ] != b (' ' ):
487
491
# deleted record
488
492
return None
@@ -535,7 +539,7 @@ def record(self, i=0):
535
539
if not self .numRecords :
536
540
self .__dbfHeader ()
537
541
i = self .__restrictIndex (i )
538
- recSize = self .__recordFmt ()[ 1 ]
542
+ recSize = self .__recStruct . size
539
543
f .seek (0 )
540
544
f .seek (self .__dbfHeaderLength () + (i * recSize ))
541
545
return self .__record ()
@@ -544,13 +548,11 @@ def records(self):
544
548
"""Returns all records in a dbf file."""
545
549
if not self .numRecords :
546
550
self .__dbfHeader ()
547
- records = []
548
551
f = self .__getFileObj (self .dbf )
549
552
f .seek (self .__dbfHeaderLength ())
550
- for i in range (self .numRecords ):
551
- r = self .__record ()
552
- if r :
553
- records .append (r )
553
+ flat = unpack (self .__recStruct .format * self .numRecords , f .read (self .__recStruct .size * self .numRecords ))
554
+ rowlen = len (self .fields ) - 1
555
+ records = list (izip (* (iter (flat ),) * rowlen ))
554
556
return records
555
557
556
558
def iterRecords (self ):
0 commit comments