科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件利用XML模板分析c#中固定长度流文件

利用XML模板分析c#中固定长度流文件

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文利用XML的映像文件来构建一个分析文件布局的分析库。这个分析库将加载映像文件,分析它并生成一个关于流文件布局的内部映像。

作者:builder.com.cn 2007年3月7日

关键字: csharp C# XML

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共19页)

固定长度的流文件中存储的数据在各数据域间没有分界符。通常固定长度流文件的布局显示为一系列字段列,每列有一个起始点和指示列位置的长度值。

这样使得开发人员可以通过文件记录分析和分离各列。通常情况下分析路径很难编码为应用,这意味着文件布局的每次改变或者需要包含一个新文件时,你不得不改变源代码和重新编译。

我最近开发的一个项目要求做大量不同的文件布局分析。文件布局将会经常改变还可能增加新的内容,也有可能需要包含新文件。我需要的是一个分析库,利用它可以引入任何数量的不同文件布局,而不需要分析员改变源代码。

解决方案

通过对这个问题的分析我想出了利用XML的映像文件来构建一个分析文件布局的分析库。这个分析库将加载映像文件,分析它并生成一个关于流文件布局的内部映像。接着我们可以使用内部映像来分析流文件并将它转换成list<T>各式的纪录。每个纪录也是以list<T>开始(一个list<list<T>>格式的集合)。

这种方案的首要困难是提供分析流文件所需的XML数据,正如我前面所说,固定长度的流文件各个域通常由它们的起始位置和所占字符长度定义。列表A中显示的XML是作为一个模板的应用实例

列表 A

<xmlversion="1.0" encoding="utf-8" ?>
<FileMap>
<FieldName="FirstName" Start="0" Length="5"/>
<FieldName="LastName" Start="5" Length="10"/>
<FieldName="Address" Start="15" Length="15"/>
<FieldName="City" Start="30" Length="14"/>
<FieldName="State" Start="44" Length="2"/>
<FieldName="Zip" Start="46" Length="5"/>
</FileMap>

正如你所看到的,XML文件简单的定义了流文件格式中指明的每个域的起始点,长度,名字。流文件中一个记录的例子如下所示:

DavidSmith 502 Gilgore AveJeffersonvilleIN47130

使用XML模板,这一行分析如下:

FirstName: "David"
LastName: "Smith "
Address: "502 Gilgore Ave"
City: "Jeffersonville"
State: "IN"
Zip: "47130"

加载XML模板

在我们设定好了XML模板之后,我们还需要加载和分析它使之成为一个可以应用的映像数据。为了分析XML模板我们将会用到一个XmlDocument对象。在模板加载成为XmlDocument对象之后,我们遍历每个域节点,生成一个list<Field>对象用来保存映像信息。列表B显示了完成本功能的代码。

列表B

privateList<Field> GetFields()
{
List<Field> fields = newList<Field>();
XmlDocument map = newXmlDocument();

//Load the mapping file into the XmlDocument
map.Load(mappingFile);

//Load the field nodes.
XmlNodeList fieldNodes = map.SelectNodes("/FileMap/Field");

//Loop through the nodes and create a field object
// for each one.
foreach (XmlNode fieldNode in fieldNodes)
{
Field field = newField();

//Set the field's name
field.Name = fieldNode.Attributes["Name"].Value;

//Set the field's length
field.Length =
Convert.ToInt32(fieldNode.Attributes["Length"].Value);

//Set the field's starting position
field.Start =?Convert.ToInt32(fieldNode.Attributes["Start"].Value);

//Add the field to the Field list.
fields.Add(field);
}

//Return the fields

this is now our map of how the flat
// file is laid out.

return fields;
}

这个方法返回值包含我们需要的将flat文件分析成为可用域的所有信息。现在我们需要遍历flat文件的每一行并分析生成一个可用的list<field>集合的映像。

分析流文件

为了分析文件,我们只需要简单地打开文件并遍历每一行进行分析,列表c为完成该功能的代码,该代码包含了每一步的详细说明。

列表C

privateList<List<Field>> ParseFile(string inputFile)
{
//Get the field mapping.
List<Field> fields = GetFields();
//Create a List<List<Field>> collection of collections.
// The main collection contains our records, and the
// sub collection contains the fields each one of our

// records contains.
List<List<Field>> records = newList<List<Field>>();

//Open the flat file using a StreamReader.
using (StreamReader reader = newStreamReader(inputFile))
{
//Load the first line of the file.
string line = reader.ReadLine();

//Loop through the file until there are no lines
// left.
while (line != null)
{
//Create out record (field collection)
List<Field> record = newList<Field>();

//Loop through the mapped fields
foreach (Field field in fields)
{
i>Field fileField = newField();

//Use the mapped field's start and length

// properties to determine where in the
// line to pull our data from.
fileField.Value =
ine.Substring(field.Start, field.Length);

//Set the name of the field.
fileField.Name = field.Name;

//Add the field to our record.
record.Add(fileField);
}

//Add the record to our record collection
records.Add(record);

//Read the next line.
line = reader.ReadLine();
}
}

//Return all of our records.
return records;
}

现在我们已经分析了流文件中的所有记录,并将每个域值分离为一个包含Field对象的list集合。遍历这个集合提取域值的代码如下。这里我们简单地打印从流文件中提取出来的信息。

foreach (List<Field> record in records)
{
foreach (Field field in record)
{this.txtResults.Text += field.Name + ": " +
field.Value + "\r\n";
}

this.txtResults.Text += "----end of record----\r\n";
}

扩展这种方案

在你的项目中自如的应用这些方法并扩展它们。我项目的最终解决方案是一个动态的可配置的灵活方案,但是它是基于本文中的思想构建的。我创建的系统可以很容易地用于处理新的文件类型,文件格式,文件位置的获得不用改变一行代码,这些都可以由XML配置/逻辑文件动态地处理。这就可以使得基代码不用改变,从而简化了实施和编译。

一个类似的解决方案还可以用于从数据库中输出流文件,这变得有点复杂。因为需要处理各种不同的域类型。例如,数值类型的域可能将零放在左边,而字符类型的域可能将空格放在右边。为了解决这个问题,你需要在XML模板中添加额外的属性。在我的例子中遇到更大的问题,需要创建一个单独的XML文件用于存储每个域类型不同的格式信息。

责任编辑:德东

查看本文国际来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章