2011|08|
2013|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|05|06|07|08|09|10|11|12|
2016|01|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|

2017-06-02 C/C++あれこれ/Excel仕様のCSVファイルの読み込みと表示 [長年日記]

/*
  C/C++あれこれ/Excel仕様のCSVファイルの読み込みと表示
 
  http://winter-tail.sakura.ne.jp/pukiwiki/index.php?C%A1%BFC%2B%2B%A4%A2%A4%EC%A4%B3%A4%EC%2FExcel%BB%C5%CD%CD%A4%CECSV%A5%D5%A5%A1%A5%A4%A5%EB%A4%CE%C6%C9%A4%DF%B9%FE%A4%DF%A4%C8%C9%BD%BC%A8
  を、私が忘れないことを目的として張り付けさせて頂きました
 
  原作者は台北猫々さん(http://winter-tail.sakura.ne.jp/index.shtml)です。
  mingwでも問題なく動いており、心より感謝申し上げます。
 
*/
 
/* ==================== okinawa.csv ========================= */
 
47201,"900 ","9000,""000","オキナワケン","ナハシ","イカニケイサイガナイバアイ","沖縄県","那覇市","以下に掲載がない場合",0,0,0,0,0,0
 
47201,"90101","9010154","オキナワケン","ナハシ","アカミネ","沖縄県","那覇市","赤嶺",0,0,0,0,0,0
 
 
/* ==================== main.cpp ========================= */
 
/*
  g++ -g main.cpp CSVReader.cpp -o CSVReader
  でmingwでコンパイルできます
 
*/
 
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
 
#include "CSVReader.h"
 
int main(void) {
  std::fstream r("c:\\okinawa.csv", std::ios::in);
  if( !r.is_open() ) {
    cerr << "Open Error! :" << endl;
    return -1;
  }
  
  CSVReader csv(r);
  vector<string> tokens;
  while( !csv.Read(tokens) ) {
    for( unsigned int i=0; i<tokens.size(); i++ ) {
      //cout << "[" << tokens[i].c_str() << "]" << endl; // ここちょっっとテスト
      printf("[%s]\n",tokens[i].c_str());
    }
  }
  csv.Close();
  return 0;
}
 
 
/* ==================== CSVReader.h ========================= */
 
/**
 * CSVファイル読み込みクラス
 * @author      台北猫々
 * @version     CVS $Id: CSVReader.h,v 1.1 2008/03/26 12:45:24 tamamo Exp $
 * @license     BSD license:
 * Copyright (c) 2008, Taipei Cat Project
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Taipei Cat Project nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#ifndef _CSVREADER_H__
#define _CSVREADER_H__
 
#include <string>
#include <vector>
#include <fstream>
using namespace std;
 
#define DEFAULT_SEPARATOR   ','
#define DEFAULT_QUOTE_CHARACTER '"'
 
class CSVReader
{
public:
 
    /**
     * コンストラクタ
     * @param stream ファイルストリーム
     * @comment セパレータ(,), エンクオート(")
     */
    CSVReader(fstream& stream);
 
    /**
     * コンストラクタ
     * @param stream ファイルストリーム
     * @param sep セパレータ
     * @comment エンクオート(")
     */
    CSVReader(fstream& stream, const char sep);
 
    /**
     * コンストラクタ
     * @param stream ファイルストリーム
     * @param sep セパレータ
     * @param quo エンクオート
     */
    CSVReader(fstream& stream, const char sep, const char quo);
 
    /**
     * デストラクタ
     */
    virtual ~CSVReader(void);
 
    /**
     * CSVファイルを1行読み込んで、分割して配列で返します。
     * @param tokens トークン(OUT)
     * @return 0:正常 -1:EOF
     */
    int Read(vector<string>& tokens);
 
    /**
     * ファイルストリームをクローズします。
     * @return 0:正常 -1:異常
     */
    int Close(void);
 
private:
 
    /**
     * ファイルから1行読み込みます。
     * @param line 行データ
     * @return >=0:読み込んだデータ長 -1:EOF
     */
    int GetNextLine(string& line);
 
    /**
     * データをパースします。
     * @param nextLine 行データ
     * @param tokens パースしたデータの配列(OUT)
     * @return 0
     */
    int Parse(string& nextLine, vector<string>& tokens);
 
    std::fstream* pstream;
    char SEPARATOR;
    char QUOTE;
 
};
 
#endif
 
/* ==================== CSVReader.cpp ========================= */
 
/**
 * CSVファイル読み込みクラス
 * @author      台北猫々
 * @version     CVS $Id: CSVReader.cpp,v 1.1 2008/03/26 12:45:24 tamamo Exp $
 * @license     BSD license:
 * Copyright (c) 2008, Taipei Cat Project
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Taipei Cat Project nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#include "CSVReader.h"
 
CSVReader::CSVReader(fstream& stream):
  SEPARATOR(DEFAULT_SEPARATOR),
  QUOTE(DEFAULT_QUOTE_CHARACTER),
  pstream(&stream)
{
  
}
 
CSVReader::CSVReader(fstream& stream, const char sep):
  SEPARATOR(sep),
  QUOTE(DEFAULT_QUOTE_CHARACTER),
  pstream(&stream)
{
}
 
CSVReader::CSVReader(fstream& stream, const char sep, const char quo):
  SEPARATOR(sep),
  QUOTE(quo),
  pstream(&stream)
{
}
 
CSVReader::~CSVReader(void)
{
}
 
int CSVReader::Read(vector<string>& tokens) {
  tokens.clear();
  
  string nextLine;
  if( GetNextLine(nextLine)<=0 ) {
    return -1;
  }
  Parse(nextLine, tokens);
  return 0;
}
 
int CSVReader::GetNextLine(string& line) {
  
  if( !pstream || pstream->eof() ) {
    return -1;
  }
  std::getline( *pstream, line );
  return (int)line.length();
}
 
int CSVReader::Parse(string& nextLine, vector<string>& tokens) {
  string token;
  bool interQuotes = false;
  do {
    if (interQuotes) {
      token += '\n';
      if (GetNextLine(nextLine)<0) {
        break;
      }
    }
    
    for (int i = 0; i < (int)nextLine.length(); i++) {
      
      char c = nextLine.at(i);
      if (c == QUOTE) {
        if( interQuotes
            && (int)nextLine.length() > (i+1)
            && nextLine.at(i+1) == QUOTE ){
          token += nextLine.at(i+1);
          i++;
        }else{
          interQuotes = !interQuotes;
          if(i>2 
             && nextLine.at(i-1) != SEPARATOR
             && (int)nextLine.length()>(i+1) 
             && nextLine.at(i+1) != SEPARATOR
             ){
            token += c;
          }
        }
      } else if (c == SEPARATOR && !interQuotes) {
        tokens.push_back(token);
        token.clear();
      } else {
        token += c;
      }
    }
  } while (interQuotes);
  tokens.push_back(token);
  return 0;
}
 
/**
 * ファイルストリームをクローズします。
 * @return 0:正常 -1:異常
 */
int CSVReader::Close(void) {
  if(pstream) {
    pstream->close();
    pstream = NULL;
  }
  return 0;
}