From 6968dea428729c687b8293e37d17e8c4834c599c Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 28 Oct 2017 18:49:01 +0800 Subject: [PATCH 1/2] Update shapefile.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add __cuttingStr function , Cut non-English UTF-8 strings, convert to the specified length of the byte string. to ensure the integrity of each UTF-8 characters, will not be cut off half a character encoding. example: w = shapefile1.Writer() w.shapeType = 1 w.autoBalance = 1 w.field('TEXT', 'C', size=10) w.field('SHORT_TEXT', 'C', size=10) w.point(121.45291, 31.27055) w.record('Hello1', '中国的汉字1') w.record('Hello1', '中国的汉字2') --- shapefile.py | 327 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 197 insertions(+), 130 deletions(-) diff --git a/shapefile.py b/shapefile.py index dbf846ac..1612bcdc 100644 --- a/shapefile.py +++ b/shapefile.py @@ -36,7 +36,7 @@ MULTIPOINTM = 28 MULTIPATCH = 31 -MISSING = [None,''] +MISSING = [None, ''] PYTHON3 = sys.version_info[0] == 3 @@ -46,6 +46,7 @@ else: from itertools import izip + def b(v): if PYTHON3: if isinstance(v, str): @@ -61,6 +62,7 @@ def b(v): # For python 2 assume str passed in and return str. return v + def u(v): if PYTHON3: # try/catch added 2014/05/07 @@ -71,32 +73,37 @@ def u(v): # the problem. This function could # be condensed further. try: - if isinstance(v, bytes): - # For python 3 decode bytes to str. - return v.decode('utf-8') - elif isinstance(v, str): - # Already str. - return v - else: - # Error. - raise Exception('Unknown input type') - except: return v + if isinstance(v, bytes): + # For python 3 decode bytes to str. + return v.decode('utf-8') + elif isinstance(v, str): + # Already str. + return v + else: + # Error. + raise Exception('Unknown input type') + except: + return v else: # For python 2 assume str passed in and return str. return v + def is_string(v): if PYTHON3: return isinstance(v, str) else: return isinstance(v, basestring) + class _Array(array.array): """Converts python tuples to lits of the appropritate type. Used to unpack different shapefile header parts.""" + def __repr__(self): return str(self.tolist()) + def signed_area(coords): """Return the signed area enclosed by a ring using the linear time algorithm. A value >= 0 indicates a counter-clockwise oriented ring. @@ -104,7 +111,8 @@ def signed_area(coords): xs, ys = map(list, zip(*coords)) xs.append(xs[1]) ys.append(ys[1]) - return sum(xs[i]*(ys[i+1]-ys[i-1]) for i in range(1, len(coords)))/2.0 + return sum(xs[i] * (ys[i + 1] - ys[i - 1]) for i in range(1, len(coords))) / 2.0 + class _Shape: def __init__(self, shapeType=NULL): @@ -125,19 +133,19 @@ def __init__(self, shapeType=NULL): def __geo_interface__(self): if self.shapeType in [POINT, POINTM, POINTZ]: return { - 'type': 'Point', - 'coordinates': tuple(self.points[0]) + 'type': 'Point', + 'coordinates': tuple(self.points[0]) } elif self.shapeType in [MULTIPOINT, MULTIPOINTM, MULTIPOINTZ]: return { - 'type': 'MultiPoint', - 'coordinates': tuple([tuple(p) for p in self.points]) + 'type': 'MultiPoint', + 'coordinates': tuple([tuple(p) for p in self.points]) } elif self.shapeType in [POLYLINE, POLYLINEM, POLYLINEZ]: if len(self.parts) == 1: return { - 'type': 'LineString', - 'coordinates': tuple([tuple(p) for p in self.points]) + 'type': 'LineString', + 'coordinates': tuple([tuple(p) for p in self.points]) } else: ps = None @@ -152,14 +160,14 @@ def __geo_interface__(self): else: coordinates.append(tuple([tuple(p) for p in self.points[part:]])) return { - 'type': 'MultiLineString', - 'coordinates': tuple(coordinates) + 'type': 'MultiLineString', + 'coordinates': tuple(coordinates) } elif self.shapeType in [POLYGON, POLYGONM, POLYGONZ]: if len(self.parts) == 1: return { - 'type': 'Polygon', - 'coordinates': (tuple([tuple(p) for p in self.points]),) + 'type': 'Polygon', + 'coordinates': (tuple([tuple(p) for p in self.points]),) } else: ps = None @@ -184,25 +192,29 @@ def __geo_interface__(self): polys.append(poly) if len(polys) == 1: return { - 'type': 'Polygon', - 'coordinates': tuple(polys[0]) + 'type': 'Polygon', + 'coordinates': tuple(polys[0]) } elif len(polys) > 1: return { - 'type': 'MultiPolygon', - 'coordinates': polys + 'type': 'MultiPolygon', + 'coordinates': polys } + class _ShapeRecord: """A shape object of any type.""" + def __init__(self, shape=None, record=None): self.shape = shape self.record = record + class ShapefileException(Exception): """An exception to handle shapefile specific problems.""" pass + class Reader: """Reads the three files of a shapefile as a unit or separately. If one of the three files (.shp, .shx, @@ -221,6 +233,7 @@ class Reader: efficiently as possible. Shapefiles are usually not large but they can be. """ + def __init__(self, *args, **kwargs): self.shp = None self.shx = None @@ -260,14 +273,11 @@ def __init__(self, *args, **kwargs): self.dbf.seek(0) except (NameError, io.UnsupportedOperation): self.dbf = io.BytesIO(self.dbf.read()) - if self.shp or self.dbf: + if self.shp or self.dbf: self.load() else: raise ShapefileException("Shapefile Reader requires a shapefile or file-like object.") - - - def load(self, shapefile=None): """Opens a shapefile from a filename or file-like object. Normally this method would be called by the @@ -288,7 +298,7 @@ def load(self, shapefile=None): except IOError: pass if not (self.shp and self.dbf): - raise ShapefileException("Unable to open %s.dbf or %s.shp." % (shapeName, shapeName) ) + raise ShapefileException("Unable to open %s.dbf or %s.shp." % (shapeName, shapeName)) if self.shp: self.__shpHeader() if self.dbf: @@ -325,7 +335,7 @@ def __shpHeader(self): self.shpLength = unpack(">i", shp.read(4))[0] * 2 # Shape type shp.seek(32) - self.shapeType= unpack("6i", 9994,0,0,0,0,0)) + f.write(pack(">6i", 9994, 0, 0, 0, 0, 0)) # File length (Bytes / 2 = 16-bit words) if headerType == 'shp': f.write(pack(">i", self.__shpFileLength())) @@ -776,7 +787,7 @@ def __shapefileHeader(self, fileObj, headerType='shp'): except error: raise ShapefileException("Failed to write shapefile bounding box. Floats required.") else: - f.write(pack("<4d", 0,0,0,0)) + f.write(pack("<4d", 0, 0, 0, 0)) # Elevation z = self.zbox() # Measure @@ -802,7 +813,7 @@ def __dbfHeader(self): headerLength = numFields * 32 + 33 recordLength = sum([int(field[2]) for field in self.fields]) + 1 header = pack('i", length)) f.seek(finish) @@ -944,28 +961,29 @@ def __dbfRecords(self): f = self.__getFileObj(self.dbf) for record in self.records: if not self.fields[0][0].startswith("Deletion"): - f.write(b(' ')) # deletion flag + f.write(b(' ')) # deletion flag for (fieldName, fieldType, size, deci), value in zip(self.fields, record): fieldType = fieldType.upper() size = int(size) - if fieldType in ("N","F"): + if fieldType in ("N", "F"): # numeric or float: number stored as a string, right justified, and padded with blanks to the width of the field. if value in MISSING: - value = str("*"*size) # QGIS NULL + value = str("*" * size) # QGIS NULL elif not deci: # force to int try: # first try to force directly to int. # forcing a large int to float and back to int # will lose information and result in wrong nr. - value = int(value) + value = int(value) except ValueError: # forcing directly to int failed, so was probably a float. value = int(float(value)) - value = format(value, "d")[:size].rjust(size) # caps the size if exceeds the field size + value = format(value, "d")[:size].rjust(size) # caps the size if exceeds the field size else: value = float(value) - value = format(value, ".%sf"%deci)[:size].rjust(size) # caps the size if exceeds the field size + value = format(value, ".%sf" % deci)[:size].rjust( + size) # caps the size if exceeds the field size elif fieldType == "D": # date: 8 bytes - date stored as a string in the format YYYYMMDD. if isinstance(value, date): @@ -973,24 +991,30 @@ def __dbfRecords(self): elif isinstance(value, list) and len(value) == 3: value = date(*value).strftime("%Y%m%d") elif value in MISSING: - value = b('0') * 8 # QGIS NULL for date type + value = b('0') * 8 # QGIS NULL for date type elif isinstance(value, str) and len(value) == 8: - pass # value is already a date string + pass # value is already a date string else: - raise ShapefileException("Date values must be either a datetime.date object, a list, a YYYYMMDD string, or a missing value.") + raise ShapefileException( + "Date values must be either a datetime.date object, a list, a YYYYMMDD string, or a missing value.") elif fieldType == 'L': # logical: 1 byte - initialized to 0x20 (space) otherwise T or F. if value in MISSING: - value = b(' ') # missing is set to space - elif value in [True,1]: + value = b(' ') # missing is set to space + elif value in [True, 1]: value = b("T") - elif value in [False,0]: + elif value in [False, 0]: value = b("F") else: - value = b(' ') # unknown is set to space + value = b(' ') # unknown is set to space else: # anything else is forced to string - value = str(value)[:size].ljust(size) + #value = b(str(value)) + value = self.__cuttingStr(str(value),size) + value = value[:size].ljust(size) + # 截取指定字节长度的字符串 + + if len(value) != size: raise ShapefileException( "Shapefile Writer unable to pack incorrect sized value" @@ -998,6 +1022,34 @@ def __dbfRecords(self): value = b(value) f.write(value) + def __cuttingStr(self, value, lens): + b_str = value.encode("utf-8") + return_str = "" + + if lens < len(b_str): + ratio = lens / len(b_str) + weight = int(ratio * len(value) + 0.5) + + if weight < len(value) - 1: + direction = -1 if len(value[:weight].encode("utf-8")) >= lens else 1 + previous = weight + for i in range(weight): + wei_value = direction * i + weight + wei_len = len(value[:wei_value].encode("utf-8")) + + if (direction > 0 and wei_len <= lens) or (direction < 0 and wei_len >= lens): + previous = wei_value + else: + previous += direction + break + return_str = value[:previous] + else: + return_str = value[:weight] + else: + return_str = value + + return return_str.encode("utf-8") + def null(self): """Creates a null shape.""" self._shapes.append(_Shape(NULL)) @@ -1024,10 +1076,10 @@ def poly(self, parts=[], shapeType=POLYGON, partTypes=[]): polyShape.parts = [] polyShape.points = [] # Make sure polygons are closed - if shapeType in (5,15,25,31): + if shapeType in (5, 15, 25, 31): for part in parts: - if part[0] != part[-1]: - part.append(part[0]) + if part[0] != part[-1]: + part.append(part[0]) for part in parts: polyShape.parts.append(len(polyShape.points)) for point in part: @@ -1125,8 +1177,8 @@ def save(self, target=None, shp=None, shx=None, dbf=None): be written exclusively using saveShp, saveShx, and saveDbf respectively. If target is specified but not shp,shx, or dbf then the target path and file name are used. If no options or specified, a unique base file name - is generated to save the files and the base file name is returned as a - string. + is generated to save the files and the base file name is returned as a + string. """ # Create a unique file name if one is not defined if shp: @@ -1138,9 +1190,9 @@ def save(self, target=None, shp=None, shx=None, dbf=None): elif not shp and not shx and not dbf: generated = False if not target: - temp = tempfile.NamedTemporaryFile(prefix="shapefile_",dir=os.getcwd()) + temp = tempfile.NamedTemporaryFile(prefix="shapefile_", dir=os.getcwd()) target = temp.name - generated = True + generated = True self.saveShp(target) self.shp.close() self.saveShx(target) @@ -1149,7 +1201,8 @@ def save(self, target=None, shp=None, shx=None, dbf=None): self.dbf.close() if generated: return target - + + class Editor(Writer): def __init__(self, shapefile=None, shapeType=POINT, autoBalance=1): self.autoBalance = autoBalance @@ -1207,12 +1260,18 @@ def point(self, x=None, y=None, z=None, m=None, shape=None, part=None, point=Non shape type.""" # shape, part, point if shape and part and point: - try: self._shapes[shape] - except IndexError: self._shapes.append([]) - try: self._shapes[shape][part] - except IndexError: self._shapes[shape].append([]) - try: self._shapes[shape][part][point] - except IndexError: self._shapes[shape][part].append([]) + try: + self._shapes[shape] + except IndexError: + self._shapes.append([]) + try: + self._shapes[shape][part] + except IndexError: + self._shapes[shape].append([]) + try: + self._shapes[shape][part][point] + except IndexError: + self._shapes[shape][part].append([]) p = self._shapes[shape][part][point] if x: p[0] = x if y: p[1] = y @@ -1221,10 +1280,14 @@ def point(self, x=None, y=None, z=None, m=None, shape=None, part=None, point=Non self._shapes[shape][part][point] = p # shape, part elif shape and part and not point: - try: self._shapes[shape] - except IndexError: self._shapes.append([]) - try: self._shapes[shape][part] - except IndexError: self._shapes[shape].append([]) + try: + self._shapes[shape] + except IndexError: + self._shapes.append([]) + try: + self._shapes[shape][part] + except IndexError: + self._shapes[shape].append([]) points = self._shapes[shape][part] for i in range(len(points)): p = points[i] @@ -1235,8 +1298,10 @@ def point(self, x=None, y=None, z=None, m=None, shape=None, part=None, point=Non self._shapes[shape][part][i] = p # shape elif shape and not part and not point: - try: self._shapes[shape] - except IndexError: self._shapes.append([]) + try: + self._shapes[shape] + except IndexError: + self._shapes.append([]) # point # part @@ -1251,7 +1316,7 @@ def point(self, x=None, y=None, z=None, m=None, shape=None, part=None, point=Non def validate(self): """An optional method to try and validate the shapefile as much as possible before writing it (not implemented).""" - #TODO: Implement validation method + # TODO: Implement validation method pass def balance(self): @@ -1270,6 +1335,7 @@ def __fieldNorm(self, fieldName): fieldName = fieldName.upper() fieldName.replace(' ', '_') + # Begin Testing def test(**kwargs): import doctest @@ -1281,7 +1347,8 @@ def test(**kwargs): if verbosity == 0 and failure_count == 0: print('All test passed successfully') return failure_count - + + if __name__ == "__main__": """ Doctests are contained in the file 'README.md'. This library was originally developed From 6ab323ebb2c54dfa103a702b1adf4b3430735818 Mon Sep 17 00:00:00 2001 From: kevine Date: Mon, 30 Oct 2017 11:53:29 +0800 Subject: [PATCH 2/2] Compatible python3 with python2 encoding issues --- .gitignore | 1 + shapefile.py | 7 +++++-- shapefile.pyc | Bin 0 -> 43790 bytes shapefiles/test/dtype.dbf | Bin 75 -> 77 bytes shapefiles/test/line.dbf | Bin 2041 -> 2203 bytes shapefiles/test/line.shp | Bin 3316 -> 3588 bytes shapefiles/test/line.shx | Bin 292 -> 308 bytes shapefiles/test/point.dbf | Bin 299 -> 299 bytes shapefiles/test/polygon.dbf | Bin 198 -> 198 bytes 9 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 shapefile.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..1c2d52b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/* diff --git a/shapefile.py b/shapefile.py index 1612bcdc..6d0a8bb1 100644 --- a/shapefile.py +++ b/shapefile.py @@ -1009,10 +1009,11 @@ def __dbfRecords(self): value = b(' ') # unknown is set to space else: # anything else is forced to string - #value = b(str(value)) + # value = b(str(value)) + # Intercepts a string of the specified byte length value = self.__cuttingStr(str(value),size) value = value[:size].ljust(size) - # 截取指定字节长度的字符串 + if len(value) != size: @@ -1023,6 +1024,8 @@ def __dbfRecords(self): f.write(value) def __cuttingStr(self, value, lens): + if isinstance(value, bytes): + value = unicode(value, 'utf-8') b_str = value.encode("utf-8") return_str = "" diff --git a/shapefile.pyc b/shapefile.pyc new file mode 100644 index 0000000000000000000000000000000000000000..075d22eb480657b4297b18261874f4fb4ab48f96 GIT binary patch literal 43790 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 literal 0 HcmV?d00001 diff --git a/shapefiles/test/dtype.dbf b/shapefiles/test/dtype.dbf index 273a1cb01825a70b8e53570337b2b56c4abd8941..02707b65b44c892f4d92d106d380a99eb3ce434a 100644 GIT binary patch delta 21 ZcmebFWo0hql4G05YR?&>;0A<1001jA1Hu3R delta 19 acmebEW@RpAk!798YR?|2;HKcGpa1|PkOPGP diff --git a/shapefiles/test/line.dbf b/shapefiles/test/line.dbf index a4eee87b115d339ec80241302ecb4bef9c647c52..266fad52b7b90e20f328d101deb510acb675844f 100644 GIT binary patch delta 18 acmey#KU-TNxs*j#Vk7Gpb^sr*1RMYW diff --git a/shapefiles/test/line.shp b/shapefiles/test/line.shp index 452d11e78eed494f885349b7caf0c3c70e6aa9dc..8724f204b019456b8a4f2472e58249abefd5511a 100644 GIT binary patch delta 28 icmew&*&;JRiiw?Rqs$E+76t|e$;lTO+Zm;RWD5XvV+bDr delta 13 UcmZpX`64+%iixdiqs$E+03go;9xs*$8Ba1pC02iSG+yDRo delta 13 UcmZ3@w3>;9xs*kABa1pC02g=y)c^nh diff --git a/shapefiles/test/polygon.dbf b/shapefiles/test/polygon.dbf index 184088dee59ca0a630806feb5ffe383f458d1bad..3d07876a5c986697117c5c98b17c49f45d7e0fd1 100644 GIT binary patch delta 12 TcmX@cc#M&Sxs*$8BFiBF7d``u delta 12 TcmX@cc#M&Sxs*kABFiBF7aRkF