2011-02-24 66 views
3

對於我爲表格文本文件創建格式化數據讀/寫功能的最佳方式是什麼?說一些調用,如:C++使用BOOST/STL/etc從文件中讀取格式化表格數據

readElement(i,j)

insertRow(elem[])

readColHeaders()

我在想,如果任何現有的包裝能做到這一點?

內部格式是製表符間隔數據或CSV。

日Thnx,埃貢·

回答

3

有很多CSV讀者,但我從來沒有發現一件好事。

最簡單的是使用boost ::記號化,以填補因您的文件矢量<矢量<串> >。更妙的方法是使用boost :: spirit(但學習曲線是過山車)。

要生成一個文件,在一個矢量上迭代<矢量<字符串> >是非常微不足道的。

0

如果您的數據很小(例如少於幾百兆字節),我會將整個文件讀入內存。爲此,您可以將其存儲在一個字符串矩陣像boost::numeric::ublas::matrix<std::string>或載體的像std::vector<std::vector<std::string> >

矢量Boost.Spirit給出了一個非常好的方式來解析這種類型的文本數據到這些結構。這可以歸結爲像解析命令:

boost::spirit::qi::phrase_parse(
    begin, 
    end, 
    // parse rule: 

     *(char_ - '\t') % '\t' 

    // end parse rule 
    space, 
    vec);` 

更多精神的例子在這裏:http://www.boost.org/doc/libs/1_46_0/libs/spirit/doc/html/spirit/qi/tutorials.html

1

沒有爲C或C沒有「標準」 CSV讀/寫器++。這並不意味着你找不到一些預先存在的庫代碼來使用,但是沒有一個庫可以統治它們。在我的工作中,我們大量使用csv文件,所以我繼續推出自己的作品,儘可能適合我的工作流程。我可以告訴你一些我在我的圖書館已經制定了相當不錯做過的事情,你應該想也做自己的事:

  • 我把數據提振向量的向量::任何。我讓用戶指定構造函數中的數據格式,類似於將格式傳遞給scanf的方式。這使用戶不必做自己的演員。我使用boost :: tokenize和boost :: lexical_cast來進行實際的分割和投射。如果你的csv文件不能適應內存,這顯然不會工作,但這對我來說很難。

  • 我可以有一個模板get(),它執行any_cast並返回正確的數據。

  • 我有列名的散列以他們的指數,以支持列名的樣子跌宕而不僅僅是位置看UPS

  • 我允許用戶指定的某種組合的「主鍵」列,然後保留一個散列,以便每行都有鍵 - >行號中的值的映射。例如,如果您正在讀取股票數據,您可能希望根據CUSIP或股票代碼找到該行,而不是將整個數據進行交叉以找到您的行。

  • 讓用戶指定大小的提示,所以你可以保留()在存儲

  • 讓用戶指定的回調函數,使他可以處理和濾波線路,他爲你讀不希望/寫他們

  • 允許用戶指定該文件需要讀/寫

  • 允許用戶在自己的列標題以通爲沒有頭文件中的文件時被鎖定

不進入語言辯論,但這個庫真的是我最初在Perl中做的事情的一個端口,並且該死的如果它不是10倍容易編寫和10倍用戶友好在Perl中使用。如果可以幫助,我不建議用C++進行csv處理。

1

要讀取製表符分隔的表分成串矢量的矢量...

#include <vector> 
#include <string> 
#include <sstream> 
#include <iostream> 

typedef std::vector<std::string> StringVec; 
typedef std::vector<StringVec> RowVec; 

RowVec readRows(std::istream& f) { 
    std::string line; 
    RowVec rows; 
    while (std::getline(f, line)) { 
     rows.push_back(StringVec()); 
     std::string entry; 
     std::istringstream linestrm(line); 
     while (std::getline(linestrm, entry, '\t')) { 
      rows.back().push_back(entry); 
     } 
    } 
    return rows; 
} 

int main() { 
    std::istringstream textFile("a\tb\tc\n1\t2\t3"); 
    RowVec rows = readRows(textFile); 
    std::cout << rows.size() << std::endl; 
    std::cout << rows[0][0] << std::endl; 
    std::cout << rows[1][2] << std::endl; 
    return 0; 
} 
相關問題