Come verificare a livello di codice se il numero di forme = numero di record della tabella?


9

Ho una manciata di circa 1000 shapefile che sono danneggiati (vedi messaggio di errore allegato). Gli shapefile sono stati generati da eCognition Developer 8. Esiste uno strumento di script che sembra riparare lo shapefile una volta identificato come corrotto.

inserisci qui la descrizione dell'immagine

Modificare:

Voglio creare uno script rapido per scorrere tutti i miei shapefile e verificare se il numero di forme corrisponde ai record della tabella. Posso contare i record della tabella usando quanto segue:

# 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

Alla fine vorrei creare una sorta di controllo logico come:

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

Come posso contare le forme direttamente senza accedere al file .dbf? O, in altre parole, qual è il modo migliore per verificare a livello di codice se il numero di forme corrisponde al numero di record della tabella?


1
Immagino che il file possa essere visualizzato, ma ciascuno degli elementi nella tabella degli attributi è rappresentato da un oggetto? questo è ciò di cui si occupa il file sbn. indipendentemente dal fatto che visualizzi il numero non corrisponde. shapefilerepairer è quello che uso.
Brad Nesom,

1
Decompilare lo script potrebbe essere utile, ma wow questo è un vecchio codice! Sono sinceramente sorpreso che funzioni ancora sugli shapefile di oggi.
Paul

1
@Brad Ho aggiornato il post per apportare correzioni. L'errore .sbn è un problema diverso che ho riscontrato e non è correlato a questo problema.
Aaron

@Brad Quando eseguo un file danneggiato tramite Shape Checker, riporta: "Record insufficienti nel file dbf - aggiunta di spazi".
Aaron

Risposte:


5

Che dire dell'uso di pyshp ? L'ho installato con pip e quello che ho provato di seguito è praticamente uscito da README :

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

Sfortunatamente (o forse per fortuna?) Non ho alcun shapefile sollevato da testare per vedere se no. di forme può! = no. dei record.

Aspetta solo un minuto, ora ho uno shapefile sollevato grazie all'idea di Kirk nei commenti qui sotto. Ho eseguito il backup del dbf, ho creato una copia dell'intero file di forma, ho eliminato alcune funzionalità, quindi ho rinominato il dbf di cui è stato eseguito il backup con l'originale, ed ecco il numero di forme <numero di record:

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

2
Forse prova a fare una copia del file shape (file, in realtà). Quindi nella copia eliminare alcune funzionalità. Quindi sostituire il dbf originale con il dbf copiato (al quale sono state eliminate alcune righe).
Kirk Kuykendall,

@KirkKuykendall - la tua idea ha funzionato, vedi le modifiche. Grazie.
Chad Cooper,

7
Nessun problema. Se hai mai bisogno che io corrompa qualche dato in più, fammelo sapere.
Kirk Kuykendall,

Grazie per l'aiuto @Chad, il modulo shapefile ha fatto il trucco. Ho pubblicato lo script finale utilizzato per controllare correttamente i miei shapefile. C'erano circa 50/1000 file corrotti.
Aaron

5

Dal suono della tua domanda, sembra che tutto ciò che vuoi davvero fare sia determinare se un file di forma ha o meno problemi con esso (in questo caso, record non corrispondenti). Se hai solo bisogno di identificare quelli con problemi, in realtà non devi contare i record nel DBF e Shapefile per determinare se è un errore. Ecco perché:

Se si tenta di eseguire la funzione GetCount su uno shapefile con conteggi di record diversi, non riuscirà con l'errore:

ERRORE 000229 : impossibile aprire. Impossibile eseguire (GetCount).

Poiché la funzione GetCount non riesce in questo scenario e tutto ciò che vuoi fare è identificare gli shapefile in errore, puoi prenderli con una clausola try / tranne nel tuo codice, invece che se / else stavi tentando in precedenza di utilizzare.

Mi sono preso la libertà di aggiungere il codice e il loop "Elenco FeatureClasses" in modo da poter testare tutti gli FC nell'area di lavoro senza doverli testare manualmente.

# 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)

Grazie Ryan, questa è una buona alternativa alla soluzione di Chad e fa anche il trucco.
Aaron

2

Il formato dello shapefile è documentato. Immagino che il numero di record nel file shp non corrisponda al numero di record nel file dbf.

Il formato del file shp è documentato qui . Quindi potresti scrivere un programma per contare il numero di forme. Il formato dbf è documentato in molti punti e dovresti essere in grado di trovare campioni per contare le righe, ad esempio qui .


Le righe in un file dBase possono essere contate in due modi: (1) un record nell'intestazione stabilisce quante righe contiene e (2) sottrae la lunghezza dell'intestazione dalla lunghezza totale del file (in byte) e dividere per la lunghezza del record ( uguale a uno più la somma delle lunghezze dei campi). Di solito è una buona idea fare entrambe le cose nel caso in cui il file venga fisicamente troncato. Indipendentemente da ciò, anche quando i conteggi corrispondono, i file .shp e .dbf sono quasi inutili senza il file .shx, che viene indicizzato nel file .shp. Quindi un rapido controllo del conteggio dei record .shx potrebbe essere migliore della lettura dell'intero file .shp.
whuber

2

Lo script allegato scorre in una directory e controlla se il numero di forme corrisponde al numero di record per ciascun file di forma.

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

L'uso della geometria di controllo dovrebbe farti passare per il primo passo.
Onus
Repair Geometry ti permetterà di selezionare l'ordine e la priorità del problema per il quale vuoi riparare.
ecco alcuni altri collegamenti alla versione precedente . Quando esegui il controllo dello shapefile, finisci con ricostruire dbf?
Questo è il passaggio che crea i record da abbinare. Una delle due cose si è verificata per causare l'errore.

  1. Lo shp ha un oggetto (spaziale) che è stato eliminato / rilasciato da un altro software / processo.
  2. Il dbf ha un record che fa riferimento a geometria nulla.
    Diverse cose possono causare questo.
    Lo shx è in realtà l'indice tra i due.
    Contare le forme senza contare i record dbf è solo metà della soluzione.

Sfortunatamente, la geometria di riparazione non cancella l'errore.
Aaron

1

Guardando l' articolo di Wikipedia sui file shape , il file .shx dovrebbe contenere un indice sul file .shp, non sul file .dbf. Quindi potrebbe essere necessario verificare se .shx e .shp si adattano insieme.

È possibile aprire un file di forma senza .dbf (il che significa che non hai una tabella di attributi), ma un indice rotto genererà un messaggio di errore.


Da chi è "non permesso"? È possibile recuperare tutte le informazioni sulle funzionalità solo dal file .shp.
whuber

1
Dal software che prevede un indice ben funzionante. Non i termini giusti, ho cambiato un po 'la risposta ...
AndreJ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.