Converting National Bridge Inventory(NBI) ASCII file to shapefile

One row is too small a sample to be conclusive, but it certainly appears to be DMS (specifically, dDDMMSSHH, with an implied west longitude). You can confirm this by scanning the file and looking for a value of 60 or larger in any of the MM or SS elements. If it is in this format, then conversion to decimal degrees is as simple as parsing out the minutes and hundredths of seconds, and dividing them by 60 and 360000 (respectively), and adding those to the degrees. Don't forget to apply negation to the longitude.

You could also read the documentation, which states that the values are degrees, minutes, and hundredths of seconds (pages 19 & 20).


I have used NBI data several times, once in this article I wrote for ArcUser years ago, and a couple of times in training sessions. Here's a function that will parse the space-delimited version of NBI and return you a list of some of the bits (haven't used it in a while, but should get you going). Also, here are the NBI data docs.

def ParseNbiFile(file_path):
    """ Parses NBI bridge file and return what we want in a list """
    # Open the text file, read it into memory
    data = open(file_path).read().splitlines()
    # Define a new, empty list object
    l = []
    # Iterate through the lines of the file, slice up the line by index
    #   position of each data column
    ln = 0
    for line in data:
    latDMS = line[129:137] 
    lonDMS = line[137:146]
    # Only process rows with valid lat/lon values
    if len(latDMS.strip()) > 0 and int(lonDMS.strip()) > 0:
        latDeg = latDMS[0:2] 
        #print latDeg
        latMin = latDMS[2:4]  
        #print latMin
        latSec = latDMS[4:6]+'.'+latDMS[6:8]  
        #print latSec
        latDD = str(int(latDeg)+(float(latMin)/60)+(float(latSec)/3600)) 
        lonDeg = lonDMS[0:3]
        #print lonDeg
        lonMin = lonDMS[3:5] 
        #print lonMin
        lonSec = lonDMS[5:7]+'.'+lonDMS[7:9]  
        #print lonSec
        lonDD = str('-'+str(int(lonDeg)+(float(lonMin)/60)+float(lonSec)/3600)) 
        yearBuilt = line[156:160]  
        strucNum = line[4:18]
        #print '\n' + str(strucNum)
        facility = line[62:80]
        # Add our line to list l
        # Do string formatting to lat/long to only display 5 decimal points
        l.extend([[strucNum, facility, ('%.5f' % float(latDD)), ('%.5f' % float(lonDD)), yearBuilt]])
    return l