在使用 Python 枚举文件时,如何忽略二进制数据 headers(或只读取序列化数据)?

How can I ignore binary data headers (or just read the serialized data) when enumerating a file with Python?

我有一个包含许多 headers 二进制数据的文件(我想这就是它),然后是文本行。我刚开始使用它,但我注意到如果我使用 Python "enumerate" 函数,它不会 appear 来读取我希望它读取的行(我正在使用 Python 2.7.8)。它没有返回我感兴趣的行。在我的文本编辑器中,我可以看到我想要的数据,但结果表明它可能是 "serialized data"?文件末尾有更多相同的二进制文件。

来自数据文件的示例(我希望跳过前 8 行): 我想从以 "curve".

开头的行开始
    ÿÿÿÿ          ENetDeedPlotter, Version=5.6.1.0, Culture=neutral, PublicKeyToken=null   QSystem.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a   Net_Deed_Plotter.SerializeData!   LinesOfDataNumberOfTractsSeditortextSedLineStract
SNoteArraySNorthArrow
Slandscape
SPaperSizeSPaperBounds
SPrinterScaleSPrinterScaleStrSAllTractsMouseOffsetNSAllTractsMouseOffsetESAllTractsNOffsetSAllTractsEOffsetSImageScroll_YSImageScroll_XSImage_YSImage_XSImageFilePath
SUpDateMapSttcSttStbSboSnb
STitleText  SDateText   SPOBLines
SLabelCornersSNAmountTract0HasBeenMovedSEAmountTract0HasBeenMoved                      Net_Deed_Plotter.LineData[]   Net_Deed_Plotter.TractData[]   System.Collections.ArrayList+Net_Deed_Plotter.PaperForm+NorthArrowStruct   !System.Drawing.Printing.PaperSize   System.Drawing.Rectangle      '         Ân40.4635w 191.02
curve right radius 953.50 arc 361.84 chord n60.5705e 359.07
s56.3005e 3.81
s19.4515w 170.63
s13.4145w 60.67
s51.0250w 155.35
n40.4635w 191.02
curve left radius 615.16 arc 202.85 chord s45.19w 201.94

示例脚本

# INPUTS TO BE UPDATED
inputNDP = r"N:\Parcels\Parcels2012-11-115.ndp"
outputTXT = r"N:\Parcels\Parcels2012-11-115.txt"
# END OF INPUTS TO BE UPDATED
fileNDP = open(inputNDP, 'r')
for line in enumerate(9, fileNDP):
    print line

结果

(9, '\x00\x01\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x0c\x02\x00\x00\x00ENetDeedPlotter, Version=5.6.1.0, Culture=neutral, PublicKeyToken=null\x0c\x03\x00\x00\x00QSystem.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\x05\x01\x00\x00\x00\x1eNet_Deed_Plotter.SerializeData!\x00\x00\x00\x0bLinesOfData\x0eNumberOfTracts\x0bSeditortext\x07SedLine\x06Stract\n')
(10, 'SNoteArray\x0bSNorthArrow\n')
(11, 'Slandscape\n')
(12, 'SPaperSize\x0cSPaperBounds\rSPrinterScale\x10SPrinterScaleStr\x16SAllTractsMouseOffsetN\x16SAllTractsMouseOffsetE\x11SAllTractsNOffset\x11SAllTractsEOffset\x0eSImageScroll_Y\x0eSImageScroll_X\x08SImage_Y\x08SImage_X\x0eSImageFilePath\n')
(13, 'SUpDateMap\x04Sttc\x03Stt\x03Stb\x03Sbo\x03Snb\n')
(14, 'STitleText\tSDateText\tSPOBLines\rSLabelCorners')
>>> 

请注意,enumerate 需要一个 start 参数,该参数仅设置数字的初始值。它不会导致它跳过任何内容。

如果你想跳过行,你需要过滤你的枚举:

x=xrange(20)
>>> for num,text in (tpl for tpl in enumerate(x) if tpl[0] >8):
...   print num,text
...
9 9
10 10
11 11
12 12
13 13
14 14
15 15
16 16
17 17
18 18
19 19

我发现由于文件是二进制格式,我需要用 open('myfile', 'rb') 而不是 open('myfile', 'r') 我从 .

那里得到了很多帮助

重写看起来像这样...

#ToDO write output file
# INPUTS TO BE UPDATED
inputNDP = r"N:\Parcels\Parcels2012-11-115.ndp"
# END OF INPUTS TO BE UPDATED
fileNDP = open(inputNDP, 'rb')
def strip_nonascii(b):
    return b.decode('ascii', errors='ignore')

n = 0
for line in fileNDP:
    if n > 5:
        if '|' in line:
            break
        print(strip_nonascii(line)).strip('\n') # + str(n)
    n += 1