0

我必须阅读以非常复杂的方式构建的发票 ascii 文件,例如:

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

里面实际上还有其他东西,但我不想让你进一步混淆。

我知道如果客户不能提供更好的结构,我就完蛋了。例如 30906 是一个不断增长的迭代数字。101639 是客户 ID。“Example Company”和“Construction Company”之间的空格是可变长度的 “Example Company”字段也可以有可变长度的空格,例如“Microsoft Corporation Redmond”。与其他字段相同。所以没有明确的方法可以从后半部分提取数据。

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

如果输入有点结构化且定义明确,您将如何防范其结构的未来变化。您将如何设计和实现阅读器。

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

4

4 回答 4

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')

Once you can parse, adding conversions is a matter of subclassing Field to define the various types (dates, amounts, etc.)

于 2008-12-16T14:05:09.077 回答
0

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

我会尝试做的是将阅读器与应用程序的其余部分尽可能分开。所以,真正的问题是,如何定义一个能够适应参数列表变化的接口。这可能并不总是可能的,但是,如果您依赖接口来读取数据,您可以更改读取器的实现而不影响系统的其余部分。

于 2008-12-16T13:44:50.693 回答
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 或者它不是以空格开头,如果是则中止。

于 2008-12-16T13:46:37.337 回答
0

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

我有一个数据库模型的内存模型,但这是给定的。如果需要 XML 输出和输入,如果我需要将发票作为数据提供到其他地方,我将有一个模型的 XML 序列化,以及一个 SAX 解析器来读入它。一些 API 可能使这变得微不足道,或者你可能只是如果您要让客户从您那里阅读,想要向您的存储库公开 Web 服务。

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

于 2008-12-16T13:49:32.273 回答