Python 2.7 使用dbf包编辑.dbf文件时发生BadDataError
我最近在unix系统上从大气模型(HYSPLIT)生成了数千个shapefile输出和附带的.dbf文件。转换器Python 2.7 使用dbf包编辑.dbf文件时发生BadDataError,python-2.7,dbf,dbase,Python 2.7,Dbf,Dbase,我最近在unix系统上从大气模型(HYSPLIT)生成了数千个shapefile输出和附带的.dbf文件。转换器txt2dbf用于将shapefile属性表(文本文件)转换为.dbf 不幸的是,出现了一些错误(可能是分隔符/字段长度错误),因为输出.dbf文件有两个问题,如下所示: dbf的某些字段包含不应该存在的数据。这些数据已从邻近油田“溢出” 添加了一个不应该存在的附加字段(它实际上来自文本文件第一条记录的一部分,“1000 201”) 这是输出dbf中第一条记录的示例(使用dbviewu
txt2dbf
用于将shapefile属性表(文本文件)转换为.dbf
不幸的是,出现了一些错误(可能是分隔符/字段长度错误),因为输出.dbf文件有两个问题,如下所示:
dbview
unix包检索):
Trajnum:10012Yyyymmdd:0111231 2
时间:300
级别:0。
1000 201: 以下是我所期望的: Trajnum:1000
Yyyymmdd:20111231
时间:2300
级别:0 另外,我正在研究如何防止这种情况再次发生,但理想情况下,我希望能够修复现有的.dbf文件。不幸的是,每次运行模型时都会删除文本文件,因此“修复”.dbf文件是唯一的选择 我处理上述问题的方法是:
dbf将确实存在的字段中的信息提取到新变量中。添加字段
和dbf。写入
(python包dbf
),然后使用dbf删除旧的不正确字段。删除字段
with dbf.Table(db) as db:
db.add_fields("TRAJNUMc C(4)") #create new fields
db.add_fields("YYYYMMDDc C(8)")
db.add_fields("TIMEc C(4)")
for record in db: #extract data from fields
dbf.write(TRAJNUMc=int(str(record.Trajnum)[:4]))
dbf.write(YYYYMMDDc=int(str(record.Trajnum)[-1:] + str(record.Yyyymmdd)[:7]))
dbf.write(TIMEc=record.Yyyymmdd[-1:] + record.Time[:])
db.delete_fields('Trajnum') # delete the incorrect fields
db.delete_fields('Yyyymmdd')
db.delete_fields('Time')
db.delete_fields('1000 201') #delete the unwanted field
db.pack()
但这会产生以下错误:
dbf.ver_2.BadDataError: record data is not the correct length (should be 31, not 30)
考虑到txt2dbf
转换中存在的明显问题,在记录数据长度中发现错误并不奇怪。然而,这是否意味着该文件已完全损坏,并且我无法提取所需的信息(令人沮丧,因为我可以看到它的存在)
编辑: 与其试图编辑“bad”.dbf文件,不如使用1。将所需数据从坏文件中提取为文本,然后2。写入一个新的dbf。(见下面Ethan Furman的评论/回答)
编辑: 我需要修复/恢复数据的错误.dbf文件示例如下: 此处可以找到创建错误dbf文件的.txt文件示例:
要修复数据并重新创建原始文本文件,此代码段应有助于:
import dbf
table = dbf.Table('/path/to/scramble/table.dbf')
with table:
fixed_data = []
for record in table:
# convert to str/bytes while skipping delete flag
data = record._data[1:].tostring()
trajnum = data[:4]
ymd = data[4:12]
time = data [12:16]
level = data[16:].strip()
fixed_data.extend([trajnum, ymd, time, level])
new_file = open('repaired_data.txt', 'w')
for line in fixed_data:
new_file.write(','.join(line) + '\n')
假设您的所有数据文件看起来都像您的示例(如果数据没有嵌入逗号,则为big),那么此粗略代码将有助于将文本文件转换为DBF:
raw_data = open('some_text_file.txt').read().split('\n')
final_table = dbf.Table(
'dest_table.dbf',
'trajnum C(4); yyyymmdd C(8); time C(4); level C(9)',
)
with final_table:
for line in raw_data:
fields = line.split(',')
final_table.append(tuple(fields))
# table has been populated and closed
当然,如果您想:
# dbf string becomes
'trajnum N; yyyymmdd D; time C(4), level N'
#appending data loop becomes
for line in raw_data:
trajnum, ymd, time, level = line.split(',')
trajnum = int(trajnum)
ymd = dbf.Date(ymd[:4], ymd[4:6], ymd[6:])
level = int(level)
final_table.append((trajnum, ymd, time, level))
要修复数据并重新创建原始文本文件,此代码段应有助于:
import dbf
table = dbf.Table('/path/to/scramble/table.dbf')
with table:
fixed_data = []
for record in table:
# convert to str/bytes while skipping delete flag
data = record._data[1:].tostring()
trajnum = data[:4]
ymd = data[4:12]
time = data [12:16]
level = data[16:].strip()
fixed_data.extend([trajnum, ymd, time, level])
new_file = open('repaired_data.txt', 'w')
for line in fixed_data:
new_file.write(','.join(line) + '\n')
假设您的所有数据文件看起来都像您的示例(如果数据没有嵌入逗号,则为big),那么此粗略代码将有助于将文本文件转换为DBF:
raw_data = open('some_text_file.txt').read().split('\n')
final_table = dbf.Table(
'dest_table.dbf',
'trajnum C(4); yyyymmdd C(8); time C(4); level C(9)',
)
with final_table:
for line in raw_data:
fields = line.split(',')
final_table.append(tuple(fields))
# table has been populated and closed
当然,如果您想:
# dbf string becomes
'trajnum N; yyyymmdd D; time C(4), level N'
#appending data loop becomes
for line in raw_data:
trajnum, ymd, time, level = line.split(',')
trajnum = int(trajnum)
ymd = dbf.Date(ymd[:4], ymd[4:6], ymd[6:])
level = int(level)
final_table.append((trajnum, ymd, time, level))
看起来从dbf文件重建文本文件然后再重新转换可能更容易——你试过了吗?谢谢,Ethan。不,我没想到要试试这个。。看起来可能是一张越狱卡。。这是不是将我使用的
txt2dbf-C7-C9-C5-C9-d,-d,-d,file.att file.dbf
命令转换为dbf2txt-C7-C9-C5-C9-d,-d,file.dbf-file.att
我没有使用这些命令,所以我不知道。它可能需要一些额外的注意,例如,C9字段将有9个字符,即使最后几个字符只是空格。根据您的输入文件的外观,这可能很好--也许您可以发布一些输入文本文件的示例行?似乎从dbf文件重建文本文件然后重新转换可能更容易--您尝试过了吗?谢谢,Ethan。不,我没想到要试试这个。。看起来可能是一张越狱卡。。这是不是将我使用的txt2dbf-C7-C9-C5-C9-d,-d,-d,file.att file.dbf
命令转换为dbf2txt-C7-C9-C5-C9-d,-d,file.dbf-file.att
我没有使用这些命令,所以我不知道。它可能需要一些额外的注意,例如,C9字段将有9个字符,即使最后几个字符只是空格。根据您的输入文件的外观,这可能很好——也许您可以发布一些输入文本文件的示例行?这看起来很有希望——感谢上面的代码。我试图运行第一个代码块来恢复原始文本,但当使用data[16:][.strip()
或常见错误dbf.ver\u 2.BadDataError:记录数据的长度不正确(应该是31,而不是30)时,我得到了错误AttributeError:'array.array'对象没有属性'strip'
当我#取出.strip()部分(分别)时,我也尝试在示例文本文件上运行第二块代码,但我得到了以下错误:dbf.ver_2.dbferor:传入数据的值太多了。
。啊,很抱歉。更新的代码片段。第一个代码片段现在就可以工作了-我可以用每一行生成一个文本文件,如下所示:1001201092300,7。。问题是第一条记录丢失,因此文本文件不是从1000201201100000开始的……将恢复的.txt转换为.dbf的第二个代码段似乎工作得很好(谢谢!)——但第一个代码段的第一条记录丢失正在传播到最终的dbf(如您所料)。这似乎真的很有希望-感谢上面的代码。我试图运行第一个代码块来恢复原始文本,但得到了错误AttributeError:'array.array'对象