Jak programowo sprawdzić, czy liczba kształtów = liczba rekordów tabeli?

9

Mam garść około 1000 plików kształtu, które są uszkodzone (patrz załączony komunikat o błędzie). Pliki kształtów zostały wygenerowane z eCognition Developer 8. Istnieje narzędzie skryptowe, które wydaje się naprawiać plik kształtowy po zidentyfikowaniu go jako uszkodzony.

wprowadź opis zdjęcia tutaj

Edytować:

Chcę utworzyć szybki skrypt do przeglądania wszystkich moich plików kształtów i sprawdzania, czy liczba kształtów pasuje do rekordów tabeli. Mogę zliczyć rekordy tabeli, korzystając z następujących czynności:

# 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

W końcu chciałbym stworzyć pewnego rodzaju kontrolę logiczną, taką jak:

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

Jak mogę liczyć kształty bezpośrednio bez dostępu do pliku .dbf? Lub innymi słowy, jaki jest najlepszy sposób programowo sprawdzić, czy liczba kształtów odpowiada liczbie rekordów tabeli?

Aaron
źródło
1
Wyobrażam sobie, że plik można wyświetlić, ale czy każdy z elementów w tabeli atrybutów jest reprezentowany przez obiekt? o to dba plik sbn. niezależnie od tego, czy wyświetla liczbę, nie pasuje. shapefilerepairer jest tym, czego używam.
Brad Nesom
1
Dekompilacja skryptu może być przydatna, ale wow, to jest stary kod! Jestem szczerze zaskoczony, że nadal działa na dzisiejszych plikach kształtu.
Paul
1
@Brad Zaktualizowałem post, aby wprowadzić poprawki. Błąd .sbn to inny problem, który miałem i nie jest on związany z tym problemem.
Aaron
@Brad Kiedy uruchamiam uszkodzony plik za pomocą narzędzia Shape Checker, zgłasza on: „Za mało rekordów w pliku dbf - dodawanie pustych miejsc”.
Aaron

Odpowiedzi:

5

Co z używaniem pyshp ? Zainstalowałem go z pipem, a to, co próbowałem poniżej, jest prawie całkowicie z README :

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

Niestety (a może na szczęście?) Nie mam żadnych podpartych plików shapefile do sprawdzenia, czy nie. kształtów może! = nie. zapisów.

Poczekaj chwilkę, dzięki pomysłowi Kirka w poniższych komentarzach mam teraz powiększony plik kształtów. Utworzyłem kopię zapasową pliku dbf, utworzyłem kopię całego pliku shapefile, usunąłem niektóre funkcje, a następnie zmieniłem nazwę kopii zapasowej pliku dbf z powrotem na oryginał i oto liczba kształtów <liczba rekordów:

>>> sf = shapefile.Reader("/Users/chad/CoalOutcrops.shp")
>>> records = sf.records()
>>> len(records)
33732
>>> shapes = sf.shapes()
>>> len(shapes)
33721
>>>
Chad Cooper
źródło
2
Może spróbuj wykonać kopię pliku kształtu (właściwie plików). Następnie w kopii usuń niektóre funkcje. Następnie zamień oryginalny plik dbf na skopiowany plik dbf (który usunął niektóre wiersze).
Kirk Kuykendall
@KirkKuykendall - Twój pomysł zadziałał, zobacz zmiany. Dzięki.
Chad Cooper
7
Nie ma problemu. Jeśli kiedykolwiek będziesz potrzebować, żebym zepsuł więcej danych, daj mi znać.
Kirk Kuykendall
Dzięki za pomoc @Chad, moduł kształtu pliku załatwił sprawę. Opublikowałem ostatni skrypt używany do pomyślnego sprawdzenia moich plików kształtów. Było około 50/1000 uszkodzonych plików.
Aaron
5

Z brzmienia twojego pytania wydaje się, że wszystko, co naprawdę chcesz zrobić, to ustalić, czy plik kształtu ma z nim problemy (w tym przypadku niezgodne rekordy). Jeśli potrzebujesz tylko zidentyfikować osoby z problemami, tak naprawdę nie musisz zliczać rekordów w pliku DBF i Shapefile, aby ustalić, czy jest to błąd. Dlatego:

Jeśli spróbujesz uruchomić funkcję GetCount na pliku shapefile, który ma różne liczby rekordów, błąd zakończy się niepowodzeniem:

BŁĄD 000229 : Nie można otworzyć. Nie można wykonać (GetCount).

Ponieważ funkcja GetCount kończy się niepowodzeniem w tym scenariuszu, a wszystko, co chcesz zrobić, to zidentyfikować pliki kształtu w wyniku błędu, możesz to złapać za pomocą klauzuli try / wyjątek w kodzie, zamiast tego, czy wcześniej próbowałeś użyć.

Pozwoliłem sobie na dodanie kodu i pętli „List FeatureClasses”, abyś mógł przetestować wszystkie FC w swoim obszarze roboczym bez konieczności ręcznego testowania każdego z nich.

# 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
źródło
Dzięki Ryan, to dobra alternatywa dla rozwiązania Chada, a także załatwia sprawę.
Aaron
2

Format pliku shapefile jest udokumentowany. Zgaduję, że liczba rekordów w pliku shp nie odpowiada liczbie rekordów w pliku dbf.

Format pliku shp jest tutaj udokumentowany . Możesz napisać program zliczający liczbę kształtów. Format dbf jest udokumentowany w wielu miejscach i powinieneś być w stanie znaleźć próbki do zliczania wierszy, np . Tutaj .

Kirk Kuykendall
źródło
Wiersze w pliku dBase można zliczyć na dwa sposoby: (1) rekord w nagłówku określa liczbę zawartych w nim wierszy i (2) odejmuje długość nagłówka od całkowitej długości pliku (w bajtach) i dzieli przez długość rekordu ( równa jeden plus suma długości pól). Zwykle dobrym pomysłem jest zrobienie obu w przypadku fizycznego obcięcia pliku. Niezależnie od tego, nawet jeśli liczby się zgadzają, pliki .shp i .dbf są prawie bezużyteczne bez pliku .shx, który indeksuje się do pliku .shp. Dlatego szybka kontrola liczby rekordów .shx może być lepsza niż odczytanie całego pliku .shp.
whuber
2

Załączony skrypt przechodzi przez katalog i sprawdza, czy liczba kształtów odpowiada liczbie rekordów dla każdego pliku kształtu.

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"
Aaron
źródło
1

Korzystanie z geometrii czeku powinno przejść przez pierwszy krok. Geometria naprawy
Onus pozwoli ci wybrać kolejność i priorytet problemu, który chcesz naprawić. oto kilka innych starszych wersji linków . Po uruchomieniu programu do sprawdzania plików shapefile zakończysz przebudowywanie dbf? To jest krok, który tworzy rekordy, które pasują. Wystąpiła jedna z dwóch rzeczy, które spowodowały błąd.


  1. Shp ma obiekt (przestrzenny), który został usunięty / upuszczony przez inne oprogramowanie / proces.
  2. Dbf ma rekord, który odwołuje się do geometrii zerowej.
    Może to powodować kilka rzeczy.
    Shx to tak naprawdę indeks między nimi.
    Liczenie kształtów bez liczenia rekordów dbf to tylko połowa rozwiązania.
Brad Nesom
źródło
Niestety geometria naprawy nie usuwa błędu.
Aaron
1

Patrząc na artykuł w Wikipedii na temat plików kształtów , plik .shx powinien zawierać indeks pliku .shp, a nie pliku .dbf. Może więc być konieczne sprawdzenie, czy .shx i .shp pasują do siebie.

Możliwe jest otwarcie pliku shapefile bez pliku .dbf (co oznacza, że ​​nie masz tabeli atrybutów), ale uszkodzony indeks wygeneruje komunikat o błędzie.

AndreJ
źródło
Przez kogo jest to „niedozwolone”? Możliwe jest odzyskanie wszystkich informacji o funkcji tylko z pliku .shp.
whuber
1
Przez oprogramowanie, które oczekuje dobrze funkcjonującego indeksu.
Niewłaściwe