C++ CSV格式文件快速读写(map法索引,特别适合于大文件大数据快速读取)

本文介绍如何利用C++的rapidcsv库,通过unittest.h和main.c进行测试,实现CSV大文件的快速读写,特别是利用map法进行高效索引。
摘要由CSDN通过智能技术生成

C++ rapidcsv

1.unittest.h

#pragma once

#ifndef _MSC_VER
#include <unistd.h>
#else
#include <io.h>
#endif

#include <fstream>
#include <string>
#include <sstream>


#define ExpectEqual(t, a, b) ExpectEqualFun<t>(a, b, #a, #b, __FILE__, __LINE__)
#define ExpectTrue(a) ExpectTrueFun(a, #a, __FILE__, __LINE__)

#define ExpectException(expr, excp)                                                           \
  do                                                                                          \
  {                                                                                           \
    bool success = false;                                                                     \
    try                                                                                       \
    {                                                                                         \
      expr;                                                                                   \
    }                                                                                         \
    catch (const excp&)                                                                       \
    {                                                                                         \
      success = true;                                                                         \
    }                                                                                         \
    catch(const std::exception& ex)                                                           \
    {                                                                                         \
      std::stringstream ss;                                                                   \
      ss << unittest::detail::FileName(__FILE__) << ":" << std::to_string(__LINE__);          \
      ss << " ExpectException failed: unexpected exception '" << typeid(ex).name();           \
      ss << "' thrown." << std::endl;                                                         \
      throw std::runtime_error(ss.str());                                                     \
    }                                                                                         \
                                                                                              \
    if (!success)                                                                             \
    {                                                                                         \
      std::stringstream ss;                                                                   \
      ss << unittest::detail::FileName(__FILE__) << ":" << std::to_string(__LINE__);          \
      ss << " ExpectException failed: expected exception '" << #excp << "' not thrown.";      \
      ss << std::endl;                                                                        \
      throw std::runtime_error(ss.str());                                                     \
    }                                                                                         \
  }                                                                                           \
  while (0)


namespace unittest
{
   
  namespace detail
  {
   
    inline std::string FileName(const std::string& pPath)
    {
   
      const std::size_t slash = pPath.rfind("/");
      std::string name = (slash != std::string::npos) ? pPath.substr(slash + 1) : pPath;
      return name;
    }
  }

  inline std::string TempPath()
  {
   
    char name[] = "rapidcsvtest.XXXXXX";
#ifndef _MSC_VER
    int fd = mkstemp(name);
    close(fd);
#else
    _mktemp_s(name, strlen(name) + 1);
#endif
    return std::string(name);
  }
  
  inline void WriteFile(const std::string& pPath, const std::string& pData)
  {
   
    std::ofstream outfile;
    outfile.open(pPath, std::ifstream::out | std::ifstream::binary);
    outfile << pData;
    outfile.close();
  }
  
  inline std::string ReadFile(const std::string& pPath)
  {
   
    std::ifstream infile;
    infile.open(pPath, std::ifstream::in | std::ifstream::binary);
    std::string data((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
    infile.close();
    return data;
  }

  inline void DeleteFile(const std::string& pPath)
  {
   
    std::remove(pPath.c_str());
  }

  template<typename T>
  inline void ExpectEqualFun(T pTest, T pRef, const std::string& testName,
                             const std::string& refName, const std::string& filePath, int lineNo)
  {
   
    if (pTest != pRef)
    {
   
      std::stringstream ss;
      ss << detail::FileName(filePath) << ":" << std::to_string(lineNo);
      ss << " ExpectEqual failed: " << testName << " != " << refName << std::endl;
      ss << testName << " = '" << pTest << "'" << std::endl;
      ss << refName << " = '" << pRef << "'" << std::endl;

      throw std::runtime_error(ss.str());
    }
  }

  inline void ExpectTrueFun(bool pTest, const std::string& testName, const std::string& filePath,
                            int lineNo)
  {
   
    if (!pTest)
    {
   
      std::stringstream ss;
      ss << detail::FileName(filePath) << ":" << std::to_string((long long)lineNo);
      ss << " ExpectTrue failed: " << testName << " == false" << std::endl;

      throw std::runtime_error(ss.str());
    }
  }
}


2.rapidcsv.h


#pragma once

#include <algorithm>
#include <cassert>
#include <cmath>
#ifdef HAS_CODECVT
#include <codecvt>
#endif
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <typeinfo>
#include <vector>
using namespace std;
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif

namespace rapidcsv
{
   
#if defined(_MSC_VER)
  static const bool sPlatformHasCR = true;
#else
  static const bool sPlatformHasCR = false;
#endif

  /**
   * @brief     Datastructure holding parameters controlling how invalid numbers (including
   *            empty strings) should be handled.
   */
  struct ConverterParams
  {
   
    /**
     * @brief   Constructor
     * @param   pHasDefaultConverter  specifies if conversion of non-numerical strings shall be
     *                                converted to a default numerical value, instead of causing
     *                                an exception to be thrown (default).
     * @param   pDefaultFloat         floating-point default value to represent invalid numbers.
     * @param   pDefaultInteger       integer default value to represent invalid numbers.
     */
    explicit ConverterParams(const bool pHasDefaultConverter = false,
                             const long double pDefaultFloat = std::numeric_limits<long double>::signaling_NaN(),
                             const long long pDefaultInteger = 0)
      : mHasDefaultConverter(pHasDefaultConverter)
      , mDefaultFloat(pDefaultFloat)
      , mDefaultInteger(pDefaultInteger)
    {
   
    }

    /**
     * @brief   specifies if conversion of non-numerical strings shall be converted to a default
     *          numerical value, instead of causing an exception to be thrown (default).
     */
    bool mHasDefaultConverter;

    /**
     * @brief   floating-point default value to represent invalid numbers.
     */
    long double mDefaultFloat;

    /**
     * @brief   integer default value to represent invalid numbers.
     */
    long long mDefaultInteger;
  };

  /**
   * @brief     Exception thrown when attempting to access Document data in a datatype which
   *            is not supported by the Converter class.
   */
  class no_converter : public std::exception
  {
   
    /**
     * @brief   Provides details about the exception
     * @returns an explanatory string
     */
    virtual const char* what() const throw()
    {
   
      return "unsupported conversion datatype";
    }
  };

  /**
   * @brief     Class providing conversion to/from numerical datatypes and strings. Only
   *            intended for rapidcsv internal usage, but exposed externally to allow
   *            specialization for custom datatype conversions.
   */
  template<typename T>
  class Converter
  {
   
  public:
    /**
     * @brief   Constructor
     * @param   pConverterParams      specifies how conversion of non-numerical values to
     *                                numerical datatype shall be handled.
     */
    Converter(const ConverterParams& pConverterParams)
      : mConverterParams(pConverterParams)
    {
   
    }

    /**
     * @brief   Converts numerical value to string representation.
     * @param   pVal                  numerical value
     * @param   pStr                  output string
     */
    void ToStr(const T& pVal, std::string& pStr) const
    {
   
      if (typeid(T) == typeid(int) ||
          typeid(T) == typeid(long) ||
          typeid(T) == typeid(long long) ||
          typeid(T) == typeid(unsigned) ||
          typeid(T) == typeid(unsigned long) ||
          typeid(T) == typeid(unsigned long long) ||
          typeid(T) == typeid(float) ||
          typeid(T) == typeid(double) ||
          typeid(T) == typeid(long double) ||
          typeid(T) == typeid(char))
      {
   
        std::ostringstream out;
        out << pVal;
        pStr = out.str();
      }
      else
      {
   
        throw no_converter();
      }
    }

    /**
     * @brief   Converts string holding a numerical value to numerical datatype representation.
     * @param   pVal                  numerical value
     * @param   pStr                  output string
     */
    void ToVal(const std::string& pStr, T& pVal) const
    {
   
      try
      {
   
        if (typeid(T) == typeid(int))
        {
   
          pVal = static_cast<T>(std::stoi(pStr));
          return;
        }
        else if (typeid(T) == typeid(long))
        {
   
          pVal = static_cast<T>(std::stol(pStr));
          return;
        }
        else if (typeid(T) == typeid(long long))
        {
   
          pVal = static_cast<T>(std::stoll(pStr));
          return;
        }
        else if (typeid(T) == typeid(unsigned))
        {
   
          pVal = static_cast<T>(std::stoul(pStr));
          return;
        }
        else if (typeid(T) == typeid(unsigned long))
        {
   
          pVal = static_cast<T>(std::stoul(pStr));
          return;
        }
        else if (typeid(T) == typeid(unsigned long long))
        {
   
          pVal = static_cast<T>(std::stoull(pStr)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值