csv解析器

头文件:
#ifndef __ClientModule_CSVFile_H__  
#define __ClientModule_CSVFile_H__  


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

typedef std:: string String;


ExpandedBlockStart.gif /** CSV文件解析器
* CSV逗号分隔值文件(Comma Separated value)规则
* 1 开头是不留空,以行为单位。
* 2 可含或不含列名,含列名则居文件第一行。
* 3 一行数据不垮行,无空行。
* 4 以半角符号,作分隔符,列为空也要表达其存在。
* 5 列内容如存在半角逗号(即,)则用半角引号(即"")将该字段值包含起来。
* 6 列内容如存在半角引号(即")则应替换成半角双引号("")转义。
* 7 文件读写时引号,逗号操作规则互逆。
* 8 内码格式不限,可为ASCII、Unicode或者其他。
*/
class CSVFile
ExpandedBlockStart.gif {
public:
    CSVFile();
    ~CSVFile();

public:
ExpandedSubBlockStart.gif    /// 打开CSV文件
    
/// @param[in] strFilename 文件名
    bool open(const char* strFilePath);  

ExpandedSubBlockStart.gif    /// 另存为CSV文件
    bool save(const char* strFilePath);

ExpandedSubBlockStart.gif    /// 保存已经打开的CSV文件
    bool save();

ExpandedSubBlockStart.gif    /// 是否已经打开有文件
    bool isOpen();

ExpandedSubBlockStart.gif    /// 根据列名获得到列索引
    int getFieldIndex(const char* fieldName);

ExpandedSubBlockStart.gif    /// 获取列数
ExpandedSubBlockStart.gif    int getColumnSize() { return mColumnCount; }

ExpandedSubBlockStart.gif    /// 获取行数
ExpandedSubBlockStart.gif    int getRowSize() { return (int)mTable.size(); }

ExpandedSubBlockStart.gif    /// 是否使用UTF8编码
    void setUTF8(bool bUtf8);

public:
ExpandedSubBlockStart.gif    /// 读取数据
    
/// @param[in] row 第几行
    
/// @param[in] column 第几列
    template<class T>  
        T Read(const int row, const int column)  
ExpandedSubBlockStart.gif    {
        //printf("CSVFile::Read(%d, %d)\n", row, column);

        
// 获取行
        int rowIndex = row - 1;
        if (row<1 || row>(int)mTable.size())
ExpandedSubBlockStart.gif        {
            printf("CSVFile::Read() CANNOT GET ROW[%d]!\n", row);
            return T();
        }
        Field& filed = mTable[rowIndex];

        // 获取列
        int columnIndex = column - 1;
        if (column<1 || column>(int)filed.size())
ExpandedSubBlockStart.gif        {
            printf("CSVFile::Read() CANNOT GET COLUMN[%d]!\n", column); 
            return T();
        }
        std::string& strData = filed[columnIndex];

        // 获取数据
        T data;
        std::stringstream ss;
        ss << strData;
        ss >> data;
        return data;
    }

    String readString(const int row, const int column)  
ExpandedSubBlockStart.gif    {
        // 获取行
        int rowIndex = row - 1;
        if (rowIndex<0 || rowIndex>(int)mTable.size()-1)
ExpandedSubBlockStart.gif        {
            printf("CSVFile::readString() CANNOT GET ROW[%d]!\n", row);
            return String();
        }
        Field& filed = mTable[rowIndex];

        // 获取列
        int columnIndex = column - 1;
        if (column<1 || column>(int)filed.size())
ExpandedSubBlockStart.gif        {
            printf("CSVFile::readString() CANNOT GET COLUMN[%d]!\n", column); 
            return String();
        }
        String& strData = filed[columnIndex];

        // 获取数据
        return strData;
    }

ExpandedSubBlockStart.gif    /// 读取数据
    
/// @param[in] row 第几行
    
/// @param[in] column 第几列
    
/// @param[in] data 写入的数据
    template<class T>  
        bool Write(const int row, const int column, T data)  
ExpandedSubBlockStart.gif    {
        //printf("CSVFile::Write(%d, %d)\n", row, column);

        int rowIndex = row - 1;
        if (rowIndex < 0)
ExpandedSubBlockStart.gif        {
            // 如果索引号为负数,则增长一行。
            mTable.push_back(Field());
            rowIndex = (int)mTable.size() - 1;
        }
        else
ExpandedSubBlockStart.gif        {
            // 行数不够,自动增长。
            while ((int)mTable.size()<row)
ExpandedSubBlockStart.gif            {
                mTable.push_back(Field());
            }
        }
        Field& filed = mTable[rowIndex];

        int columnIndex = column - 1;
        if (columnIndex < 0)
ExpandedSubBlockStart.gif        {
            // 如果索引号为负数,则增长一列。
            printf("CSVFile::Write() row number is error!\n");
            return false;
        }
        else
ExpandedSubBlockStart.gif        {
            // 列数不够,自动增长。
            while ((int)filed.size()<column)
ExpandedSubBlockStart.gif            {
                filed.push_back(std::string());
            }
        }
        std::string& strData = filed[columnIndex];

        // 写入数据
        std::stringstream ss;  
        ss << data;  
        strData = ss.str();  

        return true;
    }

ExpandedSubBlockStart.gif    /// 读取数据
    
/// @param[in] cell 列数
    
/// @param[in] data 写入的数据
    template<class T>  
        bool Push(const int cell, const T& data)  
ExpandedSubBlockStart.gif    {
        return true;
    }

ExpandedSubBlockStart.gif    /// 删除一行
    bool deleteRow(const int row);

ExpandedSubBlockStart.gif    /// 删除所有行
    bool deleteAllRow();

private:  
    typedef std::vector<std::string> Field; 
    typedef std::vector<Field> Table;

ExpandedSubBlockStart.gif    /// 读取一行数据
    void readLine(Field& field);

ExpandedSubBlockStart.gif    /// 写入一行
    void writeLine(const Field& field);

ExpandedSubBlockStart.gif    /// 解析整个文本
    bool parse();

ExpandedSubBlockStart.gif    /// 解析一行数据
    void parseLine(const char* strLine, int nSize, Field& result);
    void parseLine(const std::string& strLine, Field& result);

ExpandedSubBlockStart.gif    /// 写入一行
    void writeLine(std::fstream& file, const Field& field);

ExpandedSubBlockStart.gif    /// 读取一行数据
    void readLine(std::fstream& file, Field& field);

private:  
ExpandedSubBlockStart.gif    std::fstream    mFile;            ///< 文件流
    String            mFilePath;        ///< 文件路径

ExpandedSubBlockStart.gif    Table            mTable;            ///< 表
    Field            mHead;            ///< 表头
    String            mLine;            ///< 一行字符串,没有解析的

ExpandedSubBlockStart.gif    int                mRowCount;        ///< 行数
    int                mColumnCount;    ///< 列数

ExpandedSubBlockStart.gif    bool            m_bUtf8;        ///< UTF8编码
};  


#endif // __CSVFile_H__ 

源文件:
#include "stdafx.h"
#include "CSVFile.h" 
#include <sstream> 
#include <assert.h>
#include <iostream>
#include <stdio.h>
#include "FileUtility.h"
#include "StringUtility.h"


#pragma warning(disable: 4996)

ExpandedBlockStart.gif /* Character values */
ExpandedBlockStart.gif const  char CSV_TAB = 0x09;  ///< Tab
const char CSV_SPACE = 0x20; ///< 空白符
const char CSV_CR = 0x0d; ///< 回车符\r
const char CSV_LF = 0x0a; ///< 换行符\n
const char CSV_COMMA = ','; ///< 逗号,
const char CSV_SINGLE_QUOTE = '\''; ///< 单引号'
const char CSV_DOUBLE_QUOTE = '\"'; ///< 双引号“

namespace detail
ExpandedBlockStart.gif {
 int replace(String& src_str, const String& old_str, const String& new_str) 
ExpandedSubBlockStart.gif { 
 int count = 0; 
 int old_str_len = int(old_str.length()); 
 int new_str_len = int(new_str.length()); 
 int pos = 0; 
 while((pos=int(src_str.find(old_str,pos)))!=String::npos) 
ExpandedSubBlockStart.gif { 
 src_str.replace(pos,old_str_len,new_str); 
 pos+=new_str_len; 
 ++count; 
 } 
 return count; 
 }
}

CSVFile::CSVFile()
: mRowCount(0)
, mColumnCount(0)
, m_bUtf8( false)
ExpandedBlockStart.gif {

}

CSVFile::~CSVFile()
ExpandedBlockStart.gif {
 mFile.close();
}

bool CSVFile::open( const  char* strFilePath) 
ExpandedBlockStart.gif {
 // 检查传入的参数
 if (strFilePath == 0) return false;
 printf("begin open csv file: [%s]\n", strFilePath);

 // 检查文件是否存在
 if ( !FileUtility::fileExist(strFilePath) )
ExpandedSubBlockStart.gif {
 // 创建可读可写文件
 FILE* f = fopen(strFilePath, "w+");
 fclose(f);
 }

 // 关闭已经打开的
 if (mFile.is_open()) 
ExpandedSubBlockStart.gif {
 mFile.close();//关闭文件
 mFile.clear();//清除状态
 }

 // 打开文件
 mFile.open(strFilePath, std::ios_base::in | std::ios_base::out);
 if (!mFile.is_open()) 
ExpandedSubBlockStart.gif { 
 goto FAILED;
 }
 printf("Open csv file OK: [%s]\n", strFilePath);
 mFilePath = strFilePath;

 // 清空数据
 mTable.clear();

 // 解析文件
 return parse();

FAILED:
 printf("open csv file FAILED!: [%s]\n", strFilePath);
 return false;


bool CSVFile::save(  const  char* strFilePath )
ExpandedBlockStart.gif {
 std::fstream file(strFilePath, std::ios_base::out);

 if (!file.is_open()) return false;

 Table::iterator iter = mTable.begin();
 Table::iterator iEnd = mTable.end();
 for (;iter!=iEnd; ++iter)
ExpandedSubBlockStart.gif {
 Field& field = *iter;
 writeLine(file, field);
 }
 file.close();
 printf("save as cvs file: [%s] SUCCESS!\n", strFilePath );

 return true;
}

bool CSVFile::save()
ExpandedBlockStart.gif {
 return save(mFilePath.c_str());
}

bool CSVFile::parse()
ExpandedBlockStart.gif {
 int nRowCount = 0;
 int nCellCount = 0;
 while (!mFile.eof())
ExpandedSubBlockStart.gif {
 mTable.push_back(Field());
 Field& field = mTable.back();
 readLine(field);
ExpandedSubBlockStart.gif if (field.empty()) { mTable.pop_back(); continue; }
 if ((int)field.size()>nCellCount) nCellCount = (int)field.size();
 ++nRowCount;
 if (nRowCount==1) mHead = field;
 }
 mRowCount = nRowCount;
 mColumnCount = nCellCount;
 return true;
}

void CSVFile::parseLine(  const String& strLine, Field& result )
ExpandedBlockStart.gif {
 return parseLine(strLine.c_str(), (int)strLine.size(), result);
}

void CSVFile::parseLine( const  char* strLine,  int nSize, Field& result) 
ExpandedBlockStart.gif {
 if (strLine==0) return;

 result.clear(); 

 bool bIsInWord = false
 bool bIsHaveSpace = false
 String strCurWorld; 

 for (int i=0; i<nSize; i++) 
ExpandedSubBlockStart.gif {
 const char& ch = strLine[i]; 
 if (ch == '\0') 
ExpandedSubBlockStart.gif { 
 if (i >= 1 && strLine[i-1] == CSV_COMMA) 
ExpandedSubBlockStart.gif { 
 strCurWorld = CSV_SPACE; 
 }
 break
 } 

 bool bIsAdd = true;

 switch (ch) 
ExpandedSubBlockStart.gif {
 // 逗号
 case CSV_COMMA: 
ExpandedSubBlockStart.gif { 
 if (!bIsInWord) 
ExpandedSubBlockStart.gif { 
 // 一项结束
 result.push_back(strCurWorld); 

 bIsInWord = false
 bIsHaveSpace = false
 strCurWorld = ""; 
 bIsAdd = false
 } 
 } 
 break;

 // 双引号
 case CSV_DOUBLE_QUOTE: 
ExpandedSubBlockStart.gif { 
 if (!bIsInWord) 
ExpandedSubBlockStart.gif { 
 bIsInWord = true
 bIsHaveSpace= true
 bIsAdd = false
 } 
 else 
ExpandedSubBlockStart.gif { 
 if (CSV_DOUBLE_QUOTE == strLine[i+1]) 
ExpandedSubBlockStart.gif { 
 i++; 
 } 
 else if (bIsHaveSpace) 
ExpandedSubBlockStart.gif { 
 bIsInWord = false
 bIsAdd = false
 } 
 else 
ExpandedSubBlockStart.gif { 
 assert(0); 
 } 

 } 
 } 
 break
 default
 //bIsInWord = true; 
 break
 }; 

 if (bIsAdd) 
ExpandedSubBlockStart.gif { 
 strCurWorld += ch;
 } 

 } 

 if (!strCurWorld.empty())
ExpandedSubBlockStart.gif { 
 result.push_back(strCurWorld); 
 } 


void CSVFile::readLine( Field& field )
ExpandedBlockStart.gif {
 readLine(mFile, field);
}

void CSVFile::readLine( std::fstream& file, Field& field )
ExpandedBlockStart.gif {
 // 读取一行
 std::getline(file, mLine, '\n');
 if (mLine.empty()) return;

 // 转换编码
 if (m_bUtf8)
ExpandedSubBlockStart.gif {
 StringUtility::UTF8ToAnsi(mLine, mLine);
 }

 // 解析数据
 parseLine(mLine.c_str(), (int)mLine.size(), field);
}

void CSVFile::writeLine(  const Field& field )
ExpandedBlockStart.gif {
 writeLine(mFile, field);
}

void CSVFile::writeLine( std::fstream& file,  const Field& field )
ExpandedBlockStart.gif {
 Field::const_iterator iter =field.begin();
 Field::const_iterator iEnd =field.end();
 for (; iter!=iEnd; ++iter)
ExpandedSubBlockStart.gif {
 String str = *iter;
 detail::replace(str, "\"", "\"\"");

 // 转码
 if (m_bUtf8)
ExpandedSubBlockStart.gif {
 StringUtility::AnsiToUTF8(str, str);
 }

 // 写入内容
 if (str.find_first_of(CSV_COMMA) != String::npos)
ExpandedSubBlockStart.gif {
 // 塞两个双引号
 file << CSV_DOUBLE_QUOTE << str << CSV_DOUBLE_QUOTE;
 }
 else
ExpandedSubBlockStart.gif {
 file << str;
 }
 if ( (iter + 1) != iEnd) file << CSV_COMMA; // 写入逗号
 }
 file << std::endl;
}

int CSVFile::getFieldIndex(  const  char* fieldName )
ExpandedBlockStart.gif {
 if (fieldName==0) return -1;

 Field::const_iterator iter = mHead.begin();
 Field::const_iterator iEnd = mHead.end();
 for (; iter!=iEnd; ++iter)
ExpandedSubBlockStart.gif { 
 if (*iter == fieldName) 
ExpandedSubBlockStart.gif { 
 return int(iter - mHead.begin()); 
 } 
 } 

 return -1;
}

bool CSVFile::deleteRow(  const  int row )
ExpandedBlockStart.gif {
 int index = row - 1;
 if (index<0 || index>=(int)mTable.size()) return false;
 mTable.erase(mTable.begin()+index);
 return true;
}

bool CSVFile::deleteAllRow()
ExpandedBlockStart.gif {
 mRowCount = 0;
 mColumnCount = 0;
 mTable.clear();
 return true;
}

bool CSVFile::isOpen()
ExpandedBlockStart.gif {
 return mFile.is_open();
}

void CSVFile::setUTF8(  bool bUtf8 )
ExpandedBlockStart.gif {
 m_bUtf8 = bUtf8;
}


读取示例:
CSVFile csv;
csv.open("hello.csv");
int n = csv.Read< int>(1, 1);
std:: string str = csv.Read<std:: string>(1, 2);


写入示例:
CSVFile csv;
csv.deleteAllRow();
csv.Write< int>(1, 1, 1);
csv.Write<std:: string>(1, 2, "hello");
csv.save("hello.csv");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值