2008-12-16 9 views
0

我要读的是在一个非常令人费解的方式构成的发票ASCII文件,例如:我必须从复杂的ASCII文件中读取发票数据,您将如何防范未来的变化?

55651108 3090617.10.0806:46:32101639Example Company    Construction Company   Example Road. 9   9524 Example City 

有实际上是另外的东西在里面,但我不希望任何进一步迷惑你。

我知道如果客户不能提供更好的结构,我注定要失败。例如30906是一个增长的迭代数字。 101639是CustomerId。 “示例公司”和“建筑公司”之间的空格长度可变“示例公司”字段也可以具有可变长度的空格,但是例如“微软公司雷德蒙德”。与其他领域一样。所以没有明确的方法从后面提取数据。

但这不是问题。我被带走了。我的问题如下:

如果输入是有点结构化和明确的,你将如何防范其结构的未来变化。你将如何设计和实现一个读者。

我正在考虑在我的数据库中使用简单的EAV模型,并使用描述输入,实体名称和它们的值类型的文本或XML模板。我会根据模板解析发票文件。

回答

1

“如果输入的结构有些明确,你会如何防范其结构的未来变化?你如何设计和实现一个阅读器?”

您必须以一种可灵活选取的方式定义布局。

下面是一个Python版本

class Field(object): 
    def __init__(self, name, size): 
     self.name= name 
     self.size = size 
     self.offset= None 

class Record(object): 
    def __init__(self, fieldList): 
     self.fields= fieldList 
     self.fieldMap= {} 
     offset= 0 
     for f in self.fields: 
      f.offset= offset 
      offset += f.size 
      self.fieldMap[f.name]= f 
    def parse(self, aLine): 
     self.buffer= aLine 
    def get(self, aField): 
     fld= self.fieldMap[aField] 
     return self.buffer[ fld.offset:fld.offset+fld.size+1 ] 
    def __getattr__(self, aField): 
     return self.get(aField) 

现在你可以定义记录

myRecord= Record( 
    Field('aField',8), 
    Field('filler',1), 
    Field('another',5), 
    Field('somethingElse',8), 
) 

这给你一个合理灵活地选择分开一段输入一个战斗的机会。

myRecord.parse(input) 
myRecord.get('aField') 

一旦你可以解析,将转换为子类领域的问题来定义各种类型(日期,金额等)

0

我相信描述实体名称和值类型的模板很好。类似于文本文件的“模式”。

我试图做的是尽可能地将读者与应用程序的其余部分分开。所以,真正的问题是,如何定义一个能够适应参数列表更改的界面。这可能并非总是可行,但如果依赖接口读取数据,则可以更改读取器的实现而不影响系统的其他部分。

0

那么,你的文件格式看起来很像在银行和他们的客户之间使用的名为Etebac的法国协议。

这是一个固定宽度的文本格式。

你能做的最好是使用某种unpack功能:

$ perl -MData::Dumper -e 'print Dumper(unpack("A8 x A5 A8 A8 A6 A30 A30", "55651108 3090617.10.0806:46:32101639Example Company    Construction Company   Example Road. 9   9524 Example City"))' 
$VAR1 = '55651108'; 
$VAR2 = '30906'; 
$VAR3 = '17.10.08'; 
$VAR4 = '06:46:32'; 
$VAR5 = '101639'; 
$VAR6 = 'Example Company'; 
$VAR7 = 'Construction Company'; 

你应该做的是为每一个输入,检查它是什么它应该是,那是,XX.XX. XX或YY:YY:YY,或者它没有以空格开始,如果是,则放弃。

0

我会有一个发票数据的数据库,其中包含公司,发票,Invoice_Items等表格。取决于复杂性,是否希望记录您的订单,然后将发票链接到订单,等等?但我离题...

我会有一个内存模型的数据库模型,但这是一个给定的。如果需要XML输出和输入,那么如果我需要将发票作为其他数据提供给发票,那么我将拥有该XML模型的XML序列化,以及一个SAX解析器来读取它。有些API可能会使这些微不足道,或者您可能只是如果您要让客户读取您的信息,则希望将Web服务公开给您的存储库。

至于阅读文本文件(并没有太多有关他们的信息 - 为什么这些格式会改变?他们来自哪里?你是在替换这个系统,还是继续运行,你只是一个新的后端,他们正在提供?)你说空格的数量是可变的 - 这是因为格式是固定宽度的列?我会创建一个读取器,将它们读入您的模型,并因此读取您的数据库模式。

相关问题