zoukankan      html  css  js  c++  java
  • C++读写CSV文件

    前两天看了《Reading and Writing CSV Files in MFC》(http://www.codeproject.com/Articles/53759/Reading-and-Writing-CSV-Files-in-MFC)发现它只针对文件中的一行读写,而且只能作为一个局部变量使用,或者读,或者写,不能同时兼用,更不能作为类的变量,更别说扩展了。而且,它只支持在MFC条件下实现,如果我们需要在一个模块当中呢?在一个库中呢?在非MFC中呢?不过,它的读取遍历算法和写入算法我觉得还是不错的,所以,基于此,也根据我自己工作中的需求做了改变,也在测试中达到了比较好的结果。


    一般读取CSV文件我们是需要:

    1、既能满足MFC,又能满足非MFC;

    2、逐行读取,而不是一行,因为可能不止一行;

    3、读取一行后需要针对分隔符(一般是“,”)来分析获得所有解析后的元素项,而且每一行的元素个数都不一定相同;

    4、写入CSV时,针对每一行的元素之间都要添加分隔符(一般是“,”),甚至元素当中可能有诸如:冒号(“"”)、逗号(“,”)这样比较特殊的字符,我们又如何解决呢?

    5、作为一个封装类,留有余地便于今后的完善和扩展。


    好了,不多说了,上代码:


    XCFileStream.h


    #if _MSC_VER > 1000
    #pragma once
    #endif


    #ifndef __XCFILESTREAM_H__
    #define __XCFILESTREAM_H__


    /// 隐藏依赖文件
    /// C系统文件
    /// C++系统文件
    #include <string>
    #include <list>
    #include <vector>
    using namespace std;
    #include <windows.h>
    /// 其它库头文件
    /// 本项目头文件


    /// 无错
    #define XC_ERR_NONE 0
    /// 无效文件名或非指定文件格式
    #define XC_ERR_INVALID_FILE_NAME (-1)


    /// xun-test文件的读与写
    class CXCFileStream 
    {


    public:


    CXCFileStream(void);
    ~CXCFileStream(void);


    /*
    * 函数功能:读取CSV文件,分析其中的内容,然后存储在容器中。
    * 参数描述:
    *     [in] lpszFilename - 待读取的CSV文件;
    *     [in, out] vlStr - 存储分析后的CSV内容
    * 返回值:
    *     错误代码
    * 注意:这里因为特殊愿意(目前还不清楚),不是vector<list<string>>,而是vector<list<string> >。
    */
    const int ReadCsvData(LPCTSTR lpszFilename, vector<list<string> > &vlStr);
    /* 
    * 函数功能:将容器中的内容经过排版、布局、添加分隔符后写入到CSV文件。
    * 参数描述:
    *     [in] lpszFilename - 待读取的CSV文件;
    *     [in] vlStr - 存储分析后的CSV内容
    * 返回值:
    *     错误代码
    * 注意:这里因为特殊愿意(目前还不清楚),不是vector<list<string>>,而是vector<list<string> >。
    */
    const int WriteCsvData(LPCTSTR lpszFilename, const vector<list<string> > &vlStr);


    private:


    /// 判断是否是CSV文件
    const bool IsCsvFile(LPCTSTR lpszFilename);


    };


    #endif


    XCFileStream.cpp


    /// 隐藏依赖文件
    /// C系统文件
    /// C++系统文件
    #include <fstream> /// 读取映射文件
    #include <algorithm> 
    /// 其它库头文件
    /// 本项目头文件
    #include "XCFileStream.h"


    CXCFileStream::CXCFileStream()
    {
    }


    CXCFileStream::~CXCFileStream(void)
    {
    }


    const bool CXCFileStream::IsCsvFile(LPCTSTR lpszFilename)
    {
    /// 0、判断文件名是否有效
    if (NULL == lpszFilename || 4 > strlen(lpszFilename)) 
    return false;
    /// 本地变量
    string _strFileName(lpszFilename);
    size_t _iLen = _strFileName.length();
    string _strSuff(_strFileName.substr(_iLen - 4, 4));
    /// 转变为小写,如果要转变为大写:tolower -> toupper 。
    transform(_strSuff.begin(), _strSuff.end(), _strSuff.begin(), tolower);
    /// 1、判断是否是CSV文件
    return (0 == _strSuff.compare(".csv"));
    }


    const int CXCFileStream::ReadCsvData(LPCTSTR lpszFilename, vector<list<string> > &vlStr)
    {
    /// 1、判断是否是CSV文件
    if (! IsCsvFile(lpszFilename)) 
    return XC_ERR_INVALID_FILE_NAME;
    /// 2、打开CSV文件
    ifstream _streamFromFile(lpszFilename);
    ///    判断打开文件是否成功
    if (NULL == _streamFromFile) 
    return (-errno);
    /// 存储读取的文件内容
    string _strIn("");
    /// 3、读取一行
    while (getline(_streamFromFile, _strIn)) {
    /// 每行的源字符串
    LPCTSTR _pcSrc = _strIn.c_str();
    /// 存储一行‘,'分隔解析后的各个元素
    list<string> _ltStr;
    /// Parse values in this line
    while (*_pcSrc != '') {
    /// string to hold this value
    string _strElem(""); 
    /// 针对每个字符分析
    if (*_pcSrc == '"') {
    /// Bump past opening quote
    _pcSrc++;
    /// Parse quoted value
    while (*_pcSrc != '') {
    /// Test for quote character
    if (*_pcSrc == '"') {
    /// Found one quote
    _pcSrc++;
    // If pair of quotes, keep one
    // Else interpret as end of value
    if (*_pcSrc != '"') {
    _pcSrc++;
    break;
    }
    }
    /// Add this character to value
    _strElem.push_back(*_pcSrc++);
    }
    }
    else {
    // Parse unquoted value
    while (*_pcSrc != '' && *_pcSrc != ',') 
    _strElem.push_back(*_pcSrc++);
    // Advance to next character (if not already end of string)
    if (*_pcSrc != '')
    _pcSrc++;
    }
    /// Add this string to container
    _ltStr.push_back(_strElem);
    }
    /// 分析后的一行文件内容所得的元素列表添加到容器中
    vlStr.push_back(_ltStr);
    /// 归零,防止下次分析旧的数据。
    _strIn.assign("");
    }


    return XC_ERR_NONE;
    }


    const int CXCFileStream::WriteCsvData(LPCTSTR lpszFilename, const vector<list<string> > &vlStr)
    {
    /// 1、判断是否是CSV文件
    if (! IsCsvFile(lpszFilename)) 
    return XC_ERR_INVALID_FILE_NAME;
    /// 2、打开CSV文件
    ofstream _streamToFile(lpszFilename);
    ///    判断打开文件是否成功
    if (NULL == _streamToFile) 
    return (-errno);
    /// 本地变量
    static TCHAR chQuote = '"';
    static TCHAR chComma = ',';
    /// Loop through each list of string in vector 
    for (vector<list<string> >::const_iterator vIt = vlStr.begin(); vIt != vlStr.end(); vIt ++) {
    /// Loop through each string in list 
    for (list<string>::const_iterator lIt = vIt->begin(); lIt != vIt->end(); lIt ++) {
    /// Separate this value from previous
    if (vIt->begin() != lIt) 
    _streamToFile.put(chComma);
    /// 考虑string中可能有,或"的情况,这就要特殊包装。
    bool bComma = (lIt->find(chComma) != lIt->npos);
    bool bQuote = (lIt->find(chQuote) != lIt->npos);
    /// 真的含有,或"的情况
    if (bComma || bQuote) {
    _streamToFile.put(chQuote);


    if (bQuote) {
    for (string::const_iterator chIt = lIt->begin(); chIt != lIt->end(); chIt ++ ) {
    // Pairs of quotes interpreted as single quote
    if (chQuote == *chIt) 
    _streamToFile.put(chQuote);


    _streamToFile.put(*chIt);
    }
    }
    else 
    _streamToFile << *lIt;


    _streamToFile.put(chQuote);
    }
    else
    _streamToFile << *lIt;
    }
    /// 换行
    _streamToFile << endl;
    }
    /// 
    return XC_ERR_NONE;
    }


    如果朋友你有更好的建议或这里有问题,请根据blog抬头我的联系方式跟我取得联系,感谢你的支持和帮助。

  • 相关阅读:
    [Docker]一键部署gitlab中文版
    [Docker]python 2.7.5 docker-compose安装
    [CentOS7]pip安装
    快速傅里叶变换FFT
    HDU 4734 f(x)
    DP
    HDU 3555 Bomb
    HDU 5898 odd-even number
    将文本拷贝到剪贴板
    数论分块
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3170483.html
Copyright © 2011-2022 走看看