Last active
December 23, 2015 15:25
-
-
Save hmito/dafa0575aca71385668e to your computer and use it in GitHub Desktop.
[C++] csvファイル入出力用のiteratorを作ってみた話 ref: http://qiita.com/hmito/items/45289b60e5274796b52b
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include "csv_iterator.hpp" | |
int main(){ | |
//カンマ区切り(csv)でファイルを読みだして、タブ区切りで画面に出力する | |
auto oitr = csv::current(std::cout, csv::mode::tsv); | |
std::ifstream fin("data.csv"); | |
for(auto itr = csv::begin(fin, csv::mode::csv); itr != csv::end(fin); ++itr){ | |
*oitr++ = *itr; | |
if(itr.eol())oitr.endl(); | |
} | |
system("pause"); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::vector<std::string> StringSet = {"Red", "Blue", "Green", ...}; | |
std::ofstream fout("test.csv"); | |
auto oitr = csv::begin(fout); | |
//StringSet配列内の文字列を順に出力 | |
for(auto Str: StringSet){ | |
*oitr = Str; | |
++oitr; //次のフィールドへ | |
} | |
//改行はendlメンバ関数 | |
oitr.endl(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include "csv_iterator.hpp" | |
int main(){ | |
std::ifstream fin("data2.csv"); | |
auto itr = csv::begin(fin, csv::mode::csv); | |
//1行読み飛ばす | |
csv::advance_line(itr); | |
//名前、性別、年齢の順で読みだす | |
while(itr != csv::end(fin)){ | |
unsigned int Num; | |
(*itr++) >> Num; | |
for(unsigned int Cnt = 0; Cnt < Num; ++Cnt){ | |
std::cout << "[" << Cnt << "/" << Num << "]" << (*itr++) <<std::endl; | |
} | |
} | |
system("pause"); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<class Elem = char, class Traits = std::char_traits<Elem> > | |
class basic_ocsv_iterator : public std::iterator < std::output_iterator_tag, void, void, void, void >{ | |
private: | |
using my_type = basic_ocsv_iterator < Elem, Traits >; | |
using ostream_type = std::basic_ostream < Elem, Traits >; | |
using string_type = std::basic_string < Elem, Traits >; | |
using csv_mode_type = basic_csv_mode<Elem, Traits>; | |
private: | |
struct output_cell; | |
private: | |
ostream_type* pstream; | |
csv_mode_type CSVMode; | |
bool IsCellHead; | |
bool IsLineHead; | |
public: | |
basic_ocsv_iterator() | |
: pstream(nullptr){} | |
basic_ocsv_iterator(ostream_type& Stream_, csv_mode_type CSVMode_) | |
: pstream(&Stream_) | |
, CSVMode(CSVMode_) | |
, IsCellHead(false) | |
, IsLineHead(true){} | |
basic_ocsv_iterator(const my_type& My_) = default; | |
my_type& operator=(const my_type& My_) = default; | |
public: | |
operator bool()const{ return pstream; } | |
output_cell operator*(){ return output_cell(*this); } | |
my_type& operator++(){ | |
IsCellHead = true; | |
IsLineHead = false; | |
return *this; | |
} | |
my_type operator++(int){ | |
my_type ans(*this); | |
operator++(); | |
return ans; | |
} | |
bool eol()const{ return IsLineHead; } | |
void endl(){ | |
(*pstream) << CSVMode.End; | |
IsLineHead = true; | |
IsCellHead = false; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct output_cell{ | |
private: | |
my_type& My; | |
private: | |
void cell_head_treat(){ | |
if(My.IsCellHead && !My.IsLineHead){ | |
*(My.pstream) << My.CSVMode.Sep; | |
} | |
My.IsCellHead = false; | |
} | |
public: | |
output_cell(my_type& My_) :My(My_){} | |
void operator=(const string_type& Str){ | |
cell_head_treat(); | |
//エスケープ文字周りの処理 | |
*(My.pstream) << csv::cell_encode(Str, My.CSVMode); | |
} | |
template<typename T> | |
output_cell& operator<<(const T& Val){ | |
cell_head_treat(); | |
*(My.pstream) << Val; | |
return *this; | |
} | |
friend std::basic_istream<Elem, Traits>& operator>>(std::basic_istream<Elem, Traits>& in, output_cell p){ | |
string_type Str; | |
in >> Str; | |
p = Str; | |
return in; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::ofstream fout("test.csv"); | |
auto oitr = csv::begin(fout); | |
(*oitr++)<<32; | |
(*oitr++)<<35; | |
(*oitr++)<<40; | |
//出力:32,35,40 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::ifstream fin("data.csv"); | |
int Cell=0; | |
int Line=0; | |
for( auto itr = csv::begin(fin); itr!= csv::end(fin); ++itr){ | |
std::cout<<"["<<Line<<","<<Cell<<"]: "<<*itr; | |
if(itr.eol()){ | |
Cell=0; | |
Line++; | |
}else{ | |
Cell++; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<class Elem = char, class Traits = std::char_traits<Elem> > | |
class basic_icsv_iterator : public std::iterator < std::input_iterator_tag, std::basic_string<Elem, Traits>>{ | |
private: | |
using my_type = basic_icsv_iterator < Elem, Traits >; | |
public: | |
using sstream_type = std::basic_stringstream < Elem, Traits >; | |
using istream_type = std::basic_istream < Elem, Traits >; | |
using pos_type = typename istream_type::pos_type; | |
using string_type = std::basic_string < Elem, Traits >; | |
using csv_mode_type = basic_csv_mode<Elem, Traits>; | |
private: | |
istream_type* pstream; | |
csv_mode_type CSVMode; | |
pos_type Pos; | |
sstream_type sstream; | |
bool HasRead; | |
pos_type ReadPos; | |
bool IsLineHead; | |
private: | |
//次のフィールドまでistreamの読み込み位置を進める | |
void next(){ | |
if(HasRead){ | |
HasRead = false; | |
Pos = ReadPos; | |
} else{ | |
Elem c; | |
pstream->seekg(0, std::ios::end); | |
auto EndPos = pstream->tellg(); | |
pstream->seekg(Pos); | |
bool EscFlag = false; | |
while(pstream->tellg() != EndPos){ | |
c = pstream->get(); | |
if(c == CSVMode.End || c == EOF){ | |
IsLineHead = true; | |
break; | |
} | |
if(c == CSVMode.Sep && !EscFlag){ | |
IsLineHead = false; | |
break; | |
} | |
if(c == CSVMode.Esc){ | |
EscFlag = !EscFlag; | |
} | |
} | |
Pos = pstream->tellg(); | |
} | |
} | |
//次のフィールドの内容を読み込む | |
sstream_type& read(){ | |
if(!HasRead){ | |
Elem c; | |
sstream.str(string_type()); | |
sstream.clear(); | |
pstream->seekg(0, std::ios::end); | |
auto EndPos = pstream->tellg(); | |
pstream->seekg(Pos); | |
bool EscFlag = false; | |
while(pstream->tellg() != EndPos){ | |
c = pstream->get(); | |
if(c == CSVMode.End || c == EOF){ | |
IsLineHead = true; | |
break; | |
} | |
if(c == CSVMode.Sep && !EscFlag){ | |
IsLineHead = false; | |
break; | |
} | |
if(c == CSVMode.Esc){ | |
EscFlag = !EscFlag; | |
} | |
sstream << c; | |
} | |
ReadPos = pstream->tellg(); | |
HasRead = true; | |
} | |
return sstream; | |
} | |
private: | |
struct input_cell; | |
public: | |
basic_icsv_iterator() :pstream(nullptr){} | |
basic_icsv_iterator(istream_type& Stream_, pos_type Pos_, csv_mode_type CSVMode_, bool IsLineHead_) | |
: pstream(&Stream_) | |
, CSVMode(CSVMode_) | |
, Pos(Pos_) | |
, sstream() | |
, HasRead(false) | |
, IsLineHead(IsLineHead_){} | |
input_cell operator*(){ return input_cell(*this); } | |
my_type& operator++(){ | |
next(); | |
return *this; | |
} | |
my_type operator++(int){ | |
basic_icsv_iterator ans(*this); | |
operator++(); | |
return ans; | |
} | |
bool eol()const{ return IsLineHead; } | |
bool eof(){ | |
pstream->seekg(0, std::ios::end); | |
return Pos == pstream->tellg(); | |
} | |
friend bool operator==(const my_type& my1, const my_type& my2){ | |
if(&my1 == &my2)return true; | |
if(my1.pstream != my2.pstream) return false; | |
return my1.Pos == my2.Pos; | |
} | |
friend bool operator!=(const my_type& my1, const my_type& my2){ return !(my1 == my2); } | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct input_cell{ | |
private: | |
my_type& My; | |
public: | |
input_cell(my_type& My_) :My(My_){} | |
operator string_type(){ return csv::cell_decode(My.read().str(), My.CSVMode); } | |
template<typename T> | |
input_cell& operator>>(T& Val){ | |
My.read() >> Val; | |
return *this; | |
} | |
friend std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& out, input_cell p){ | |
return out << static_cast<string_type>(p); | |
} | |
friend bool operator==(const input_cell& in, const string_type& str){return in.raw_str() == str;} | |
friend bool operator!=(const input_cell& in, const string_type& str){ return in.raw_str() != str; } | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::ifstream fin("data.csv"); | |
auto itr = csv::begin(fin); | |
double a; | |
int b; | |
//doubleで読み込み | |
(*itr++)>>a; | |
//intで読み込み | |
(*itr++)>>b; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include <string> | |
#include <vector> | |
#include "csv_iterator.hpp" | |
int main(){ | |
std::vector<std::string> Names; | |
std::vector<bool> IsFemales; | |
std::vector<int> Ages; | |
std::ifstream fin("data.csv"); | |
auto itr = csv::begin(fin, csv::mode::csv); | |
//1行読み飛ばす | |
csv::advance_line(itr); | |
//名前、性別、年齢の順で読みだす | |
while(itr != csv::end(fin)){ | |
//文字列なら直接読み出し可能 | |
Names.push_back(*itr++); | |
if(itr.eol())continue; | |
//当然、文字列との比較も可能 | |
IsFemales.push_back(*itr++ == "F"); | |
if(itr.eol())continue; | |
//型を指定して読み出すことも可能 | |
Ages.push_back((*itr++).read<int>()); | |
} | |
std::cout << "=name=" << std::endl; | |
for(const auto& val : Names)std::cout << val << std::endl; | |
std::cout << std::endl; | |
std::cout << "=sex=" << std::endl; | |
for(auto val : IsFemales)std::cout << val << std::endl; | |
std::cout << std::endl; | |
std::cout << "=age=" << std::endl; | |
for(auto val : Ages)std::cout << val << std::endl; | |
std::cout << std::endl; | |
system("pause"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment