65,186
社区成员




#pragma once
class FND_DSG_API CCSVTools
{
private:
CCSVTools();
~CCSVTools();
public:
static void ExportToCSVFile(const CString& strFileName, const std::vector<std::vector<CString>>& data);
static std::vector<std::vector<CString>> ImportDataFromCSV(const CString& strFileName);
};
CSVTools.cpp
#include "stdafx.h"
#include <fstream>
#include "CSVTools.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace std;
CCSVTools::CCSVTools()
{
}
CCSVTools::~CCSVTools()
{
}
// 按CVS文件格式对一行数据进行解析,格式:单元格内容可用半角双引号引起来,如果内容中没有逗号,
// 则双引号可以省略,否则必须要双引号,每一个单元格的内容之间用半角逗号相隔,最后一个数字之后
// 不能有双引号,如果单元格中有双引号则用两个连续的双引号表示一个双引号
vector<CString> SplitCVSRow(const CString& row)
{
vector<CString> result;
CString oneCell = _T("");
for (int i = 0; i < row.GetLength(); /* Nothing */)
{
if (_T('\"') == row[i])
{
int j = i + 1;
while (j < row.GetLength())
{
if (j >= row.GetLength()) break; // 没有配对,且已经到最后一个字符
if (_T('\"') == row[j])
{
if (j + 1 >= row.GetLength()) break; // 已经是配对的双引号且到最后一个字符
if (_T('\"') == row[j + 1])
{
oneCell += _T("\""); // 内含两个双引号,是内容,存入文字串中
j += 2; // 必须跳到下一个字符
continue;
}
else
{
// j + 1处不是双引号,说明j处的双引号已经是与i配对的结束双引号
if (_T(',') == row[j + 1])
j += 2;
else
j += 1;
break;
}
}
else
{
oneCell += row[j];
++j;
}
}
// 双引号对应的一整个单元格处理完毕
result.push_back(oneCell);
oneCell = _T("");
i = j;
}
else if (_T(',') == row[i])
{
result.push_back(oneCell);
oneCell = _T("");
++i;
}
else
{
oneCell += row[i];
++i;
}
}
if (_T("") != oneCell) result.push_back(oneCell); // 最后一个数存起来
return result;
}
void CCSVTools::ExportToCSVFile(const CString& strFileName, const vector<vector<CString>>& data)
{
if (data.empty()) return;
CStdioFile file(strFileName, CFile::modeCreate | CFile::modeWrite);
try
{
CString strFileText;
CString strCell;
// 将数据转为逗号分隔每一行
for (size_t i = 0; i < data.size(); ++i)
{
const vector<CString>& dataRow = data[i];
for (size_t j = 0; j < dataRow.size(); ++j)
{
strCell = dataRow[j];
strCell.Replace(_T("\""), _T("\"\"")); // 单元格中有双引号,写到文件要变为两个连续双引号
if (-1 != strCell.Find(_T(',')) || -1 != strCell.Find(_T('\"')))
strCell = _T("\"") + strCell + _T("\""); // 单元格中包含了逗号和双引号,则整个内容要有双引号括起来
strFileText += strCell;
if (j < dataRow.size() - 1) strFileText += _T(","); // 最后一个后面不要逗号
}
if (i < data.size()) strFileText += _T("\n");
}
file.WriteString(strFileText);
}
catch (CException*)
{
// Nothing;
}
file.Close();
}
std::vector<std::vector<CString>> CCSVTools::ImportDataFromCSV(const CString& strFileName)
{
vector<vector<CString>> data;
try
{
ifstream ifs;
ifs.open(strFileName);
string strRow;
while (getline(ifs, strRow))
{
CString strTRow = CStringTools::stringToCString(strRow);
vector<CString> vecRow = SplitCVSRow(strTRow);
if (vecRow.empty()) continue;
data.push_back(vecRow);
}
ifs.close();
}
catch (...)
{
return data;
}
// 确保所有行的数据列一样多,列按最大列计算,不足的数据以空格填充
size_t szMax = 0;
for (auto& x : data)
if (x.size() > szMax) szMax = x.size();
if (0 == szMax)
{
data.clear();
}
else
{
for (auto& x : data)
x.resize(szMax, _T(""));
}
return data;
}