首页 > 技术文章 > .csv文件读取

SkyflyBird 2015-05-26 20:22 原文

一,介绍

  .csv文件俗称逗号分割值文件,其文件以纯文本形式存储表格数据。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。该文件由任意数目的记录组成,记录间以某种换行符隔开,比如'\n'。每条记录由字段组成,字段见的分隔符最常见的为逗号或制表符组成。

  比如***.csv文件格式:  

  1,sj_mino1001.jpg,715281,4FB55FE8,

  2,sj_mino1002.jpg,715282,4FB55FE8,

  3,sj_mino1003.jpg,715283,4FB55FE8,

  4,sj_mino1004.jpg,715285,4FB55FE8,

  通常情况下,.csv文件的生成可将 .xlsx文件另存为,保存格式为.csv格式,然后保存即可。打开该文件查看内容,可使用记事本,notepad++,word等等。

 

二,程序使用

  .csv文件最为广泛的应用是在程序之间转换数据使用,以上述数据为例,程序编写的大致思路:

  (1)以打开文件方式打开.csv表格,通过文件指针划分出每一行(可使用strchr()函数来获取行),并使用循环将将每行数据insert插入到std::map<int,std::string>的对象中(int:行号,std::string: 每行的字符串)

  (2)每行的数据是以','分割的,可参考使用strtok()函数进行分割,来获取对应的子数据。然后使用std::map对象存储。

  以下,是借助于广大的程序猿们所查找到的相关资料,网址:

  http://blog.csdn.net/zlhy_/article/details/8764250 

三, 示例代码:

========================csv.h=========================

#pragma once

#include <assert.h>
#include <map>
#include <vector>
#include <string>

using namespace std;
typedef unsigned long u32;

class CppCSV
{
public:
  CppCSV(){}
  CppCSV(const char *path)
  {
    assert(LoadCSV(path));
  }
  ~CppCSV(){}

  bool LoadCSV(const char *path);
  bool SaveCSV(const char *path = NULL);

  bool GetIntValue(u32 uiRow, u32 uiCol, int &riValue);
  bool GetFloatValue(u32 uiRow, u32 uiCol, float &rfValue);
  string* GetStringValue(u32 uiRow, u32 uiCol);

  int GetParamFromString(string str, vector<string> &stringVec, char delim = ',');


  std::map<u32, map<u32, string>>& GetCSVMap();

  void GetSkillRecordMapTable();

private: 
  std::map<u32, map<u32, string>>   m_stringMap; 
  string m_CSVName; 
};

 

==========================csv.cpp============================= 

#include <stdio.h>

#include "csv.h" 

bool CppCSV::LoadCSV(const char *path)
{
  FILE *pFile = fopen(path, "r");

  if (pFile)
  {
    fseek(pFile, 0, SEEK_END);
    u32 uSize = ftell(pFile);
    rewind(pFile); // 将文件内部的指针重新指向一个流的开头

    char *fileBuffer = new char[uSize];
    fread(fileBuffer, 1, uSize, pFile);

    map<u32, string> stringMap;
    u32 uiIndex = 1;
    char *pBegin = fileBuffer;
    char *pEnd = strchr(pBegin, '\n'); // 查找字符串首先出现'\n'的位置

    pBegin = pEnd + 1; 
    pEnd = strchr(pBegin, '\n');

    while (pEnd) 
    { 
      string strTemp; 
      strTemp.insert(0, pBegin, pEnd-pBegin); 
      assert(!strTemp.empty()); 
      stringMap[uiIndex++] = strTemp; 
      pBegin = pEnd + 1; 
      pEnd = strchr(pBegin, '\n'); 
    } 

    delete []fileBuffer;
    fileBuffer = NULL;
    pBegin = NULL;
    pEnd = NULL;

    map<u32, string>::iterator iter = stringMap.begin();
    for (; iter != stringMap.end(); ++iter)
    {
      vector<string> stringVec;
      map<u32, string> stringMapTemp;
      assert(GetParamFromString(iter->second, stringVec) > 0);

      vector<string>::size_type idx = 0;
      for (; idx != stringVec.size(); ++idx)
      {
        stringMapTemp[idx + 1] = stringVec[idx];
      }

      m_stringMap[iter->first] = stringMapTemp;
    }

    fclose(pFile);
    m_CSVName = path;
    return true;
  }
  else
  {
    return false;
  }
}

bool CppCSV::SaveCSV(const char *path /* = NULL */)
{
  if (path != NULL)
  {
    m_CSVName = path;
  }

  FILE *pFile = fopen(m_CSVName.c_str(), "w");
  if (pFile)
  {
    map<u32, map<u32, string>>::iterator iter = m_stringMap.begin();
    for (; iter != m_stringMap.end(); ++iter)
    {
      map<u32, string> &rStringMap = iter->second;
      map<u32, string>::iterator it = rStringMap.begin();
      for (; it != rStringMap.end(); ++it)
      {
        string strTemp = it->second;
        strTemp += ',';
        fwrite(strTemp.c_str(), 1, 1, pFile);
      }

      char delim = '\n';
      fwrite(&delim, 1, 1, pFile);
    }

    fclose(pFile);
    return true;
  }
  else
  {
    return false;
  }
}

bool CppCSV::GetIntValue(u32 uiRow, u32 uiCol, int &riValue)
{
   string *pStr = GetStringValue(uiRow, uiCol);
   if (pStr)
   {
      riValue = atoi(pStr->c_str());
      return true;
   }
   else
   {
      return false;
   }
}

bool CppCSV::GetFloatValue(u32 uiRow, u32 uiCol, float &rfValue)
{
  string *pStr = GetStringValue(uiRow, uiCol);
  if (pStr)
  {
    rfValue = atof(pStr->c_str());
    return true;
  }
  else
  {
    return false;
  }
}

string* CppCSV::GetStringValue(u32 uiRow, u32 uiCol)
{
  map<u32, map<u32, string>>::iterator iter = m_stringMap.find(uiRow);
  if (iter != m_stringMap.end())
  {
    map<u32, string> &rStrMap = iter->second;
    map<u32, string>::iterator it = rStrMap.find(uiCol);
    if (it != rStrMap.end())
    {
      return &(it->second);
    }
    else
    {
      return NULL;
    }
  }
  else
  {
    return NULL;
  }
}

//用于分割字符串,将CSV表格中的一行按照规则解析成一组字符串,存储在一个vector中
//根据CSV表格中所存储的数据的不同,重载各函数
int CppCSV::GetParamFromString(string str, vector<string> &stringVec, char delim)
{
  char *token = strtok(const_cast<char *>(str.c_str()), &delim);
  while (token)
  {
    string strTemp = token;
    stringVec.push_back(strTemp);
    token = strtok(NULL, &delim);
  }

  return stringVec.size();
}

void CppCSV::GetSkillRecordMapTable()
{
    map<u32, map<u32, string>>::iterator iter = m_stringMap.begin();
    for (; iter != m_stringMap.end(); ++iter)
    {
      //
    }
}

map<u32, map<u32, string>>& CppCSV::GetCSVMap()
{
    return m_stringMap;
}

 

====================测试程序main.cpp============

void main()
{
  // 二进制读取
  CppCSV cs("***.csv");
  map<u32, map<u32, string>> stringMap = cs.GetCSVMap();  // 自此可设置断点,查看数据   

  system("pause");

}

 学习自当共勉,感谢原作者的奉献!

推荐阅读