通過上文的內(nèi)容,已經(jīng)了解到S-57文件符合ISO/IEC 8211作為其數(shù)據(jù)封裝標(biāo)準(zhǔn)膳音。一個文件已分成若干個邏輯記錄(LR)召衔,每一個LR有三個基本元素頭標(biāo)區(qū)(對應(yīng)類S57Leader
)、目錄區(qū)(對應(yīng)類S57Directory
)和字段區(qū)祭陷,其中文件中的第一個LR為DDR(存儲文件中實際數(shù)據(jù)的描述和邏輯結(jié)構(gòu)苍凛,對應(yīng)類S57DDR
),其他的LR為DR(存儲文件中的實際數(shù)據(jù)兵志,對應(yīng)類S57DR
)醇蝴。
依照上圖,新建類Iso8211File
解析S-57文件想罕,主要包含一個S57DDR
字段和一個List<S57DR>
列表悠栓。由于DDR和DR的頭標(biāo)區(qū)與目錄區(qū)格式一致霉涨,因此將字段S57Leader
和字段S57Directory
放到類S57LR
中,讓DDR和DR繼承自LR惭适。DDR的字段區(qū)包含字段控制字段和數(shù)據(jù)描述字段笙瑟,因此類S57DDR
還包含字段S57FieldControlField
和字段S57DataDescriptiveFields
。DR的字段區(qū)解析邏輯與DDR不一樣癞志,因此類S57DR
還包含字段S57FieldArea
往枷。最后得到如下代碼結(jié)構(gòu):
public class S57LR
{
public S57Leader Leader; //頭標(biāo)區(qū)
public S57Directory Directory; //目錄區(qū)
}
public class S57DDR : S57LR
{
public S57FieldControlField FieldControlField; //字段區(qū) 字段控制字段
public S57DataDescriptiveFields DataDescriptiveFields; //字段區(qū) 數(shù)據(jù)描述字段
}
public class S57DR : S57LR
{
public S57FieldArea FieldArea; //字段區(qū) 字段控制字段
}
public class Iso8211File
{
public S57DDR DDR;
public List<S57DR> DRs;
}
接下來,完成Iso8211File的構(gòu)造函數(shù)凄杯,輸入?yún)?shù)為S-57文件的路徑错洁。首先解析出文件的DDR頭標(biāo)區(qū)、目錄錄戒突、字段控制字段和數(shù)據(jù)描述字段屯碴,利用其信息,循環(huán)解析出其他DR膊存,具體代碼如下:
//構(gòu)造函數(shù)窿锉,傳入S57文件路徑
public Iso8211File(string filePath)
{
DDR = new S57DDR();
DRs = new List<S57DR>();
//加載S57文件,得到二進制數(shù)據(jù)
BytesHelper.Load(filePath);
//DDR 頭標(biāo)區(qū)
DDR.Leader = new S57Leader();
//DDR 目錄區(qū)
DDR.Directory = new S57Directory(DDR.Leader);
//DDR 字段區(qū)
//DDR 字段控制字段
var tag0000 = DDR.Directory.Items[0];
DDR.FieldControlField = new S57FieldControlField(tag0000.FieldLength, DDR.Leader.FieldTagSize);
//DDR 數(shù)據(jù)描述字段
DDR.DataDescriptiveFields = new S57DataDescriptiveFields(DDR.Directory);
//循環(huán)解析DR
while (BytesHelper.Position < BytesHelper.ENCBytes.Length - 2)
{
var dr = new S57DR();
//DR 頭標(biāo)區(qū)
dr.Leader = new S57Leader();
//DR 目錄區(qū)
dr.Directory = new S57Directory(dr.Leader);
//DR 字段區(qū)
dr.FieldArea = new S57FieldArea(dr.Directory, DDR.DataDescriptiveFields);
DRs.Add(dr);
}
}
最后驗證結(jié)果:
var reader = new Iso8211File("..\\US4AK7IM.000");
var dl = reader.DDR.Leader;
var header = dl.RecordLength.ToString() + dl.FieldControlString
+ dl.FieldAreaBaseAddress.ToString() + dl.ExCharacterSetIndicator
+ dl.FieldLengthSize.ToString() + dl.FieldPositionSize.ToString()
+ dl.Reserved.ToString() + dl.FieldTagSize.ToString();
Console.WriteLine("DDR頭標(biāo)區(qū):" + header);
Console.WriteLine("DDR目錄區(qū):");
foreach (var di in reader.DDR.Directory.Items)
{
Console.WriteLine($"標(biāo)簽:{di.Tag}\t長度:{di.FieldLength}\t位置:{di.FieldPosition}");
}
Console.WriteLine("DR的個數(shù)為:" + reader.DRs.Count);
至此膝舅,S-57文件的解析部分已全部完成了嗡载,我們可以清楚的掌握文件中的每一個標(biāo)簽,各標(biāo)簽下都有什么屬性仍稀,各屬性的值是什么洼滚。但不同標(biāo)簽對應(yīng)真實世界實體的什么?不同的屬性代表什么含義技潘?各屬性的值又能說明什么遥巴?需要對S-57標(biāo)準(zhǔn)的進一步解讀。