2013-05-10 64 views
0

循環假設我有以下格式的文件。檢查文件頭,然後通過

date|time|account 
2010-01-01|07:00:00|A1 
2010-01-01|07:00:01|A2 
.... 

假設我有以下功能。

def ReadLongFile(longFile) 
    CSV.foreach(longFile, :headers => true, :col_sep => '|') do |row| 
    p row.to_hash 
    end 
end 

我喜歡這個功能,因爲它可以讓我存儲每個線作爲哈希其中報頭條目是鍵,以及所述線的條目中的相應值。但是,修改它的最有效方法是什麼,以便我可以驗證標題是否包含正確的條目?我正在考慮兩種選擇。首先,我可以打開另一個函數並檢查第一行。其次,我可以在函數中檢查,但它會執行每次迭代的檢查。

回答

1

我會建議使用CSV::header_row函數來執行檢查,並提出一個錯誤,如果它不是你所期望的。喜歡的東西:

def ReadLongFile(longFile) 
    CSV.foreach(longFile, :headers => true, :return_headers => true, :col_sep => '|') do |row| 
    if row.header_row? then 
     raise ArgumentError, "Bad headers" unless header_sane?(row) 
    end 
    # Otherwise do the processing 
    end 
end 

你的header_sane?實行將執行您需要確保該文件是你希望它是什麼樣的驗證。您的調用代碼可以解救ArgumentError(如果它可以從中恢復),或者只是讓它失敗:-)

注意:已更新以反映以下注釋中指出的錯誤。撥打CSV::foreach時務必設置:return_headers選項。

如果您擔心調用header_row的最小開銷?對於每個行條目,可以構造一個CSV實例並使用shift在繼續之前手動檢查第一行。例如:

def ReadLongFile(longFile) 
    File.open(longFile) do |file| 
    reader = CSV.new(file, {:col_sep => '|', :headers => true, :return_headers => true}) 
    header_row = reader.shift 
    raise ArgumentError, "Bad file headers" unless header_sane?(header_row) 
    reader.each do |row| 
     p row 
    end 
    end 
end 

實現如上,以下行爲也適用:

[4] pry(main)> def header_sane? row 
[4] pry(main)* true 
[4] pry(main)* end 
=> nil 
[5] pry(main)> ReadLongFile("file.csv") 
#<CSV::Row "date":"2010-01-01" "time":"07:00:00" "account":"A1"> 
#<CSV::Row "date":"2010-01-01" "time":"07:00:01" "account":"A2"> 
=> nil 
[6] pry(main)> def header_sane? row 
[6] pry(main)* false 
[6] pry(main)* end 
=> nil 
[7] pry(main)> ReadLongFile("file.csv") 
ArgumentError: Bad file headers 
from (pry):7:in `block in ReadLongFile' 
+0

這是不正確。你的函數中的第一個'is_header?'應該是'header_row?'。此外,有必要將':return_headers'設置爲true。 – idealistikz 2013-05-10 19:31:39

+1

@idealistikz相應更新 - 謝謝! – 2013-05-10 19:35:00