牵着老婆满街逛

严以律己,宽以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

使用boost::spirit实现的CSV文件解析类

boost::spirit真是不错的说。。。。

#include <iostream>
#include 
<iterator>
#include 
<vector>
#include 
<string>

#include 
<boost/spirit/core.hpp>
#include 
<boost/spirit/iterator/file_iterator.hpp>

using namespace std;
using namespace boost::spirit;

template
<typename IteratorT>
struct LineInfo 
{
    IteratorT lineIter;
    size_t lineNum;

    LineInfo( IteratorT beg ) : lineIter(beg), lineNum(
1{ }
}
;

template
<typename IteratorT>
struct NewLine
{
    LineInfo
<IteratorT>& lineInfo;
    NewLine( LineInfo
<IteratorT>& info ) : lineInfo(info) { }

    
void operator()(IteratorT first, IteratorT last) const
    
{
        lineInfo.lineIter 
= last;
        lineInfo.lineNum
++;
    }

}
;

struct AddVal
{
    vector
<string>& values;
    AddVal( vector
<string>& vec ) : values(vec) { }

    template
<class IteratorT>
    
void operator()(IteratorT first, IteratorT last) const
    
{
#ifdef _MSC_VER
        
string s;
        s.resize(distance(first, last));
        
for (size_t i = 0; first != last; ++i) 
        
{
            s[i] 
= *first++;
        }

#else
        
string s( first, last );
#endif
        
string::size_type pos = 0;
        
while (1)
        
{
            pos 
= s.find("\"\"", pos);
            
if (pos == string::npos)
                
break;
            
++pos;
            s.erase(pos, 
1);
        }

        values.push_back(s);
    }

}
;

template
<class IteratorT>
struct CSVParser : public grammar<CSVParser<IteratorT> >
{
    vector
<string>& v;
    LineInfo
<IteratorT>& lineInfo;

    CSVParser( vector
<string>& vec, LineInfo<IteratorT>& info ) : v(vec), lineInfo(info) { }

    template 
<typename ScannerT>
    
struct definition 
    
{
        rule
<ScannerT> csv, val, quoted_val, naked_val;

        definition(
const CSVParser<IteratorT>& self)
        
{
            csv 
= val >> *(',' >> val) >>
                (eol_p[NewLine
<IteratorT>(self.lineInfo)] | end_p);

            val 
= *blank_p >>
                ch_p(
'\"'>> quoted_val[AddVal(self.v)] >> ch_p('\"'>>
                
*blank_p
                
| naked_val[AddVal(self.v)];

            quoted_val 
= *(eol_p[NewLine<IteratorT>(self.lineInfo)]
            
| ~ch_p('"'| str_p("\"\""));

            naked_val 
= *(~ch_p(','& ~ch_p('\"'& ~ch_p('\n'));
        }


        
const rule<ScannerT>& start() const return csv; }
    }
;
}
;

template
<typename IteratorT>
parse_info
<IteratorT>
parse_csv( 
const IteratorT& first, const IteratorT& last,
          vector
<string>& vec, LineInfo<IteratorT>& info )
{
    CSVParser
<IteratorT> csv(vec, info);

    
return parse(first, last, csv);
}


int main( int argc, char** argv)
{
    
if (argc != 2return 1;

    typedef file_iterator
<char> iterator_t;

    iterator_t begin(argv[
1]);
    
if (!begin)
    
{
        cout 
<< "Unable to open file: " << argv[1<< endl;
        
return -1;
    }


    iterator_t first 
= begin;

    iterator_t last 
= first.make_end();

    LineInfo
<iterator_t> line_info( begin );
    
while ( first != last )
    
{
        vector
<string> v;
        parse_info
<iterator_t> info = parse_csv( first, last, v, line_info );

        
if (!info.hit)
        
{
            cout 
<< "Error!!  Line: " << line_info.lineNum
                
<< ", Column: " << distance(line_info.lineIter, info.stop)+1 << endl;
            
break;
        }


        cout 
<< "Parses OK:" << endl;
        
for (vector<string>::size_type i = 0; i < v.size(); ++i)
            cout 
<< i+1 << "" << v[i] << endl;

        cout 
<< "-------------------------\n";

        first 
= info.stop;
    }


    
return 0;
}

posted on 2008-06-03 22:55 杨粼波 阅读(3008) 评论(1)  编辑 收藏 引用

评论

# re: 使用boost::spirit实现的CSV文件解析类 2008-09-30 10:07 A0soft

显然作者的功底不错。虽然在VC++6下面编译通不过,但是在VC++8(VS2005)下面非常顺利,连一个警告都没有。
命令行里的指出的文件好像只能排他打开。  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理