前两天看了《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 != '\0') {
/// string to hold this value
string _strElem(""); 
/// 针对每个字符分析
if (*_pcSrc == '"') {
/// Bump past opening quote
_pcSrc++;
/// Parse quoted value
while (*_pcSrc != '\0') {
/// 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 != '\0' && *_pcSrc != ',') 
_strElem.push_back(*_pcSrc++);
// Advance to next character (if not already end of string)
if (*_pcSrc != '\0')
_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抬头我的联系方式跟我取得联系,感谢你的支持和帮助。

C++读写CSV文件的更多相关文章

  1. 用opencsv文件读写CSV文件

    首先明白csv文件长啥样儿: 用excel打开就变成表格了,看不到细节 推荐用其它简单粗暴一点儿的编辑器,比如Notepad++, csv文件内容如下: csv文件默认用逗号分隔各列. 有了基础的了解 ...

  2. 使用Python读写csv文件的三种方法

    Python读写csv文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 前言 逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是 ...

  3. python3读写csv文件

    python读取CSV文件   python中有一个读写csv文件的包,直接import csv即可.利用这个python包可以很方便对csv文件进行操作,一些简单的用法如下. 1. 读文件 csv_ ...

  4. python读写csv文件

    文章链接:https://www.cnblogs.com/cloud-ken/p/8432999.html Python读写csv文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 前言 逗 ...

  5. 利用JavaCSV API来读写csv文件

    http://blog.csdn.net/loongshawn/article/details/53423121 http://javacsv.sourceforge.net/ 转载请注明来源-作者@ ...

  6. 使用 Apache Commons CSV 读写 CSV 文件

    有时候,我们需要读写 CSV 文件,在这里给大家分享Apache Commons CSV,读写 CSV 文件非常方便. 具体官方文档请访问Apache Commons CSV. 官方文档已经写得很详细 ...

  7. python3使用csv包,读写csv文件

    python操作csv,现在很多都用pandas包了,不过python还是有一个原始的包可以直接操作csv,或者excel的,下面举个例子说明csv读写csv文件的方法: import os impo ...

  8. C/C++读写csv文件

    博客转载自:http://blog.csdn.net/u012234115/article/details/64465398 C++ 读写CSV文件,注意一下格式即可 #include <ios ...

  9. JAVA读写CSV文件

    最近工作需要,需要读写CSV文件的数据,简单封装了一下 依赖读写CSV文件只需引用`javacsv`这个依赖就可以了 <dependency> <groupId>net.sou ...

  10. (Python基础教程之十二)Python读写CSV文件

    Python基础教程 在SublimeEditor中配置Python环境 Python代码中添加注释 Python中的变量的使用 Python中的数据类型 Python中的关键字 Python字符串操 ...

随机推荐

  1. Loadrunner结果分析Graphs

    Transactions(用户事务分析)----用户事务分析是站在用户角度进行的基础性能分析. Transation Sunmmary(事务综述)----对事务进行综合分析是性能分析的第一步,通过分析 ...

  2. Log4Qt 使用(一)

    一.下载 http://sourceforge.net/projects/log4qt/develop 二.Log4Qt介绍 Log4Qt 是Apache Log4J 的Qt移植版,所以看Log4J的 ...

  3. Word03-文档中的截图显示不全

    今天写文档时遇到个很蛋疼的问题,在doc文档中复制进去的截图总是显示不全,图片上半部分都被文字遮盖了,折腾半天,最后还是网上找到了答案. 解决方法如下: 将图片所在行的段落行距修改为其它值即可,原来为 ...

  4. SqlServer跨域查询

    SELECT * FROM OPENDATASOURCE('SQLOLEDB','Data Source=192.168.1.14;User ID=sa;Password=sql.com').eBui ...

  5. linux分区和系统文件和挂载

    要以root用户进入 .查看磁盘情况 lsblk .进行分区 sudo cfdisk /dev/sda 在空闲资源的地方新建分区,然后一步步的走下来就行了,最后选择write,然后quit 重启 .创 ...

  6. poj3252 组合数学

    题目大意:给两个数字a,b求出[a,b]中转化成二进制后0的个数大于等于1的个数的数 例如1100转化成10-11,100-111,1000-1011,1100.保证每个区段都有1打头,然后有一段数字 ...

  7. linux int to string 方法

    最近从windows 移植程序的时候发现to_string()函数在linux 中不能用,网上找了几种方法,觉得使用stringstream对象来实现类型转化比较好一点. 你只需在你工程中加入下面的t ...

  8. JavaScript加密解密压缩工具

    <script> a=62; function encode() { var code = document.getElementById('code').value; code = co ...

  9. IIC 概述之源码仿真

    7.1.1 I2C总线简介 1.I2C总线的基本结构 I2C总线由数据线SDA和时钟线SCL构成,每条线都通过上拉电阻接向正电源,所有采用I2C接口标准的器件均并行挂接在总线上,如图7-1所示. I2 ...

  10. C语言写猜拳游戏中遇到的函数循环小问题

    各位可能在初学C语言的时候都有写过猜拳游戏.但在写猜拳的函数时,避免不了会使用循环. 当函数被套在一个循环中的时候,你的计分变量可能就会被重置为函数体里的初始值.那么怎么解决这个问题? 其实很简单,你 ...