2008-12-16 23 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服務公開給您的存儲庫。

至於閱讀文本文件(並沒有太多有關他們的信息 - 爲什麼這些格式會改變?他們來自哪裏?你是在替換這個系統,還是繼續運行,你只是一個新的後端,他們正在提供?)你說空格的數量是可變的 - 這是因爲格式是固定寬度的列?我會創建一個讀取器,將它們讀入您的模型,並因此讀取您的數據庫模式。

相關問題