Как программно проверить, если число фигур = количество записей в таблице?

9

У меня есть около 1000 шейп-файлов, которые повреждены (см. Прикрепленное сообщение об ошибке). Шейп-файлы были сгенерированы из eCognition Developer 8. Существует инструмент-скрипт, который, похоже, восстанавливает шейп-файл, если он идентифицирован как поврежденный.

введите описание изображения здесь

Редактировать:

Я хочу создать быстрый скрипт, который будет перебирать все мои шейп-файлы и проверять, совпадает ли количество фигур с записями таблицы. Я могу посчитать записи таблицы, используя следующие:

# Name: fcCount.py
# Purpose: calculate the number of features in a featureclass

# Import system modules
import arcpy
from arcpy import env

env.workspace = "C:/data"
Sample = "MyShp.shp"
result_dbf = int(arcpy.GetCount_management(Sample).getOutput(0)) 
print result_dbf

В конечном итоге я хотел бы создать какую-то проверку логики, такую ​​как:

if result_dbf = result_shp:
    pass
else:
    print "There is a problem with" + str(Sample)

Как я могу считать фигуры напрямую, не обращаясь к файлу .dbf? Или, другими словами, как лучше всего программно проверить, совпадает ли число фигур с количеством записей в таблице?

Аарон
источник
1
Я предполагаю, что файл можно просмотреть, но каждый ли элемент в таблице атрибутов представлен объектом? Об этом позаботится файл sbn. независимо от того, отображается ли номер, не совпадает. Я использую shapefilerepairer.
Брэд Несом
1
Декомпиляция скрипта может быть полезна, но вау, это какой-то старый код! Я искренне удивлен, что он все еще работает с современными шейп-файлами.
Пол
1
@Brad Я обновил пост, чтобы внести исправления. Ошибка .sbn - это другая проблема, с которой я столкнулся и не связана с этой проблемой.
Аарон
@Brad Когда я запускаю поврежденный файл через Shape Checker, он сообщает: «Недостаточно записей в файле dbf - добавление пробелов».
Аарон

Ответы:

5

Как насчет использования pyshp ? Я установил его с помощью pip, и то, что я попробовал ниже, в значительной степени прямо из README :

>>> import shapefile
>>> sf = shapefile.Reader("/Users/chad/CoalOutcrops.shp")
>>> shapes = sf.shapes()
>>> len(shapes)
33732
>>> records = sf.records()
>>> len(records)
33732
>>>

К сожалению (или, к счастью, к счастью?), У меня нет поднятых шейп-файлов, чтобы проверить, нет ли. форм может! = нет. записей.

Подожди минутку, у меня теперь есть поднятый шейп-файл благодаря идее Кирка в комментариях ниже. Я сделал резервную копию dbf, сделал копию всего шейп-файла, удалил некоторые функции, затем переименовал резервную копию dbf обратно в оригинал, и вот, количество фигур <количество записей:

>>> sf = shapefile.Reader("/Users/chad/CoalOutcrops.shp")
>>> records = sf.records()
>>> len(records)
33732
>>> shapes = sf.shapes()
>>> len(shapes)
33721
>>>
Чед Купер
источник
2
Может быть, попробуйте сделать копию файла формы (файлы, на самом деле). Затем в копии удалите некоторые функции. Затем замените исходный dbf на скопированный dbf (у которого было удалено несколько строк).
Кирк Куйкендалл
@KirkKuykendall - ваша идея сработала, смотрите правки. Спасибо.
Чед Купер
7
Нет проблем. Если вам когда-нибудь понадобится, чтобы я испортил еще какие-то данные, просто дайте мне знать.
Кирк Кайкендалл
Спасибо за помощь @Chad, модуль shapefile сделал свое дело. Я опубликовал последний скрипт, используемый для успешной проверки моих шейп-файлов. Было около 50/1000 поврежденных файлов.
Аарон
5

Судя по звучанию вашего вопроса, кажется, что все, что вы действительно хотите сделать, - это определить, есть ли проблемы с шейп-файлом (в данном случае несовпадающие записи). Если вам просто нужно идентифицировать тех, у кого есть проблемы, вам на самом деле не нужно подсчитывать записи в DBF и Shapefile, чтобы определить, нет ли в них ошибок. Вот почему:

Если вы попытаетесь запустить функцию GetCount для шейп-файла с другим количеством записей, произойдет сбой с ошибкой:

ОШИБКА 000229 : невозможно открыть. Не удалось выполнить (GetCount).

Так как функция GetCount завершается с ошибкой в ​​этом сценарии, и все, что вам нужно сделать, это идентифицировать шейп-файлы по ошибке, вы можете поймать это с помощью выражения try / исключением в вашем коде вместо if / else, который вы ранее пытались использовать.

Я позволил себе добавить код и цикл «List FeatureClasses», чтобы вы могли проверить все FC в вашем рабочем пространстве без необходимости вручную проверять каждый из них.

# Import system modules
import arcpy
from arcpy import env

env.workspace = "C:/data"

fcList = arcpy.ListFeatureClasses()

for fc in fcList:
    try:
        result_dbf = int(arcpy.GetCount_management(fc).getOutput(0))
        print fc + ": " + str(result_dbf) + " records"
    except:
        print "There is a problem with: " + str(fc)
RyanKDalton
источник
Спасибо Райан, это хорошая альтернатива решению Чада, а также делает свое дело.
Аарон
2

Формат шейп-файла задокументирован. Я предполагаю, что количество записей в файле shp не соответствует количеству записей в файле dbf.

Формат файла shp документирован здесь . Таким образом, вы можете написать программу для подсчета количества фигур. Формат dbf задокументирован во многих местах, и вы сможете найти образцы для подсчета строк, например, здесь .

Кирк Куйкендалл
источник
Строки в файле dBase могут быть подсчитаны двумя способами: (1) запись в заголовке определяет, сколько строк она содержит, и (2) вычитает длину заголовка из общей длины файла (в байтах) и делит на длину записи ( равно одному плюс сумма длин полей). Обычно это хорошая идея, если файл физически урезан. В любом случае, даже если количество совпадений совпадает, файлы .shp и .dbf практически бесполезны без файла .shx, который индексируется в файле .shp. Так что быстрая проверка количества записей .shx может быть лучше, чем чтение всего файла .shp.
whuber
2

Прикрепленный скрипт проходит по каталогу и проверяет, совпадает ли количество фигур с количеством записей для каждого шейп-файла.

import arcpy, os, shapefile
from arcpy import env

env.workspace = r"C:\path\to\shapefiles"
Dir = env.workspace

fclist = arcpy.ListFeatureClasses()

for fc in fclist:

    myfc = os.path.join(Dir, fc)
    sf = shapefile.Reader(str(myfc))
    shapes = sf.shapes()
    shape_total = len(shapes)
    records = sf.records()
    record_total = len(records)

    if shape_total != record_total:
        print "There is a problem with " + str(fc)
    else:
        print str(fc) + " passed"
Аарон
источник
1

Использование геометрии чека должно помочь вам пройти первый шаг.
Onus
Repair Geometry позволит вам выбрать порядок и приоритет проблемы, которую вы хотите устранить.
Вот некоторые другие ссылки более старой версии . Когда вы запускаете проверку шейп-файлов, тогда вы заканчиваете с перестройкой dbf?
Это шаг, который создает записи для соответствия. Произошла одна из двух причин возникновения ошибки.

  1. У shp есть объект (пространственный), который был удален / удален другим программным обеспечением / процессом.
  2. DBF имеет запись, которая ссылается на нулевую геометрию.
    Несколько вещей могут вызвать это.
    Shx на самом деле является индексом между ними.
    Подсчет фигур без подсчета записей dbf - это только половина решения.
Брэд Несом
источник
К сожалению, геометрия ремонта не устраняет ошибку.
Аарон
1

Глядя на статью в википедии о шейп-файлах , файл .shx должен содержать индекс в файле .shp, а не в файле .dbf. Так что может быть необходимо проверить, подходят ли .shx и .shp вместе.

Можно открыть шейп-файл без .dbf (что означает, что у вас нет таблицы атрибутов), но неправильный индекс вызовет сообщение об ошибке.

Andrej
источник
Кем это "не разрешено"? Можно восстановить всю информацию о функции только из файла .shp.
whuber
1
По программному обеспечению, которое ожидает хорошо функционирующий индекс. Не правильные термины, я немного изменил ответ ...
AndreJ