diff --git a/example/text_io_ex.cpp b/example/text_io_ex.cpp index d5dfac5..cc54073 100644 --- a/example/text_io_ex.cpp +++ b/example/text_io_ex.cpp @@ -42,13 +42,13 @@ int main(int argc, char const *argv[]) try //display_vector(name); _1s_array name; - //tc.get_column("Name_s", name); - //name.show(std::cout, ','); + tc.get_column("Name_s", name); + name.show(std::cout, ','); tc.get_row("AUS", name); name.show(std::cout, ','); - tc.save_csv("out", BothHead); + tc.save_csv("out"); /* geodsv_io tc; diff --git a/lib/io/dsv_io.cpp b/lib/io/dsv_io.cpp index a5e6fee..0cd67e3 100644 --- a/lib/io/dsv_io.cpp +++ b/lib/io/dsv_io.cpp @@ -29,15 +29,14 @@ gctl::dsv_io::dsv_io() { - // 设置基础参数 file_ = ""; - corner_name_ = "row-idx"; att_sym_ = '#'; tag_sym_ = '!'; deli_sym_ = ' '; head_num_ = 0; row_num_ = 0; col_num_ = 0; + thead_ = ColumnHead; } gctl::dsv_io::~dsv_io() @@ -47,35 +46,33 @@ gctl::dsv_io::~dsv_io() gctl::dsv_io::dsv_io(std::string filename, std::string file_exten, table_headtype_e t) { - // 设置基础参数 file_ = ""; - corner_name_ = "row-idx"; att_sym_ = '#'; tag_sym_ = '!'; deli_sym_ = ' '; head_num_ = 0; row_num_ = 0; col_num_ = 0; - // 载入文本内容 - load_text(filename, file_exten, t); + thead_ = ColumnHead; + + if (file_exten == ".csv") load_csv(filename, t); + else load_text(filename, file_exten, t); } void gctl::dsv_io::clear() { file_ = ""; - corner_name_ = "row-idx"; att_sym_ = '#'; tag_sym_ = '!'; deli_sym_ = ' '; head_num_ = 0; row_num_ = 0; col_num_ = 0; + thead_ = ColumnHead; + destroy_vector(heads_); destroy_vector(annotates_); destroy_vector(tags_); - destroy_vector(lines_); - destroy_vector(col_names_); - destroy_vector(row_names_); destroy_vector(table_); return; } @@ -95,6 +92,7 @@ void gctl::dsv_io::load_text(std::string filename, std::string file_exten, table // 校正头信息行数 head_num_ = heads_.size(); + std::vector lines; while (std::getline(infile, tmp_line)) { if (tmp_line.empty()) continue; // 跳过空行 @@ -115,18 +113,12 @@ void gctl::dsv_io::load_text(std::string filename, std::string file_exten, table tmp_line.erase(tmp_line.find_last_not_of(" \t") + 1); annotates_.push_back(tmp_line); } - else lines_.push_back(tmp_line); + else lines.push_back(tmp_line); } infile.close(); - - std::string head_str = ""; - if (t == ColumnHead || t == BothHead) - { - head_str = lines_[0]; - lines_.erase(lines_.begin()); - } - row_num_ = lines_.size(); + // 首先初始化行数 + row_num_ = lines.size(); table_.resize(row_num_); int cn; @@ -134,8 +126,9 @@ void gctl::dsv_io::load_text(std::string filename, std::string file_exten, table for (size_t i = 0; i < row_num_; i++) { tmp_cols.clear(); - parse_string_to_vector(lines_[i], deli_sym_, tmp_cols); + parse_string_to_vector(lines[i], deli_sym_, tmp_cols); + // 动态调整列数 cn = tmp_cols.size(); col_num_ = std::max(cn, col_num_); @@ -146,6 +139,7 @@ void gctl::dsv_io::load_text(std::string filename, std::string file_exten, table } } + // 补齐可能的空格 cell_content empty_cell; empty_cell.str_ = ""; for (size_t i = 0; i < row_num_; i++) @@ -157,39 +151,9 @@ void gctl::dsv_io::load_text(std::string filename, std::string file_exten, table } } - if (t == ColumnHead || t == BothHead) - { - parse_string_to_vector(head_str, deli_sym_, col_names_); - - for (size_t i = col_names_.size(); i < col_num_; i++) - { - col_names_.push_back("col-" + std::to_string(i + 1)); - } - } - - if (t == RowHead || t == BothHead) - { - col_num_ -= 1; // 列数目减一 - if (t == BothHead) - { - corner_name_ = col_names_[0]; - col_names_.erase(col_names_.begin()); - } - - row_names_.resize(row_num_); - for (size_t i = 0; i < row_num_; i++) - { - row_names_[i] = table_[i][0].str_; - table_[i].erase(table_[i].begin()); - } - - for (size_t i = row_names_.size(); i < row_num_; i++) - { - row_names_.push_back("row-" + std::to_string(i + 1)); - } - } - + thead_ = t; file_ = filename + file_exten; + destroy_vector(lines); return; } @@ -200,18 +164,8 @@ void gctl::dsv_io::load_csv(std::string filename, table_headtype_e t) return; } -void gctl::dsv_io::save_text(std::string filename, std::string file_exten, table_headtype_e t) +void gctl::dsv_io::save_text(std::string filename, std::string file_exten) { - if ((t == ColumnHead || t == BothHead) && col_names_.empty()) - { - throw std::runtime_error("[gctl::dsv_io::save_text] Row/Column names not instored."); - } - - if ((t == RowHead || t == BothHead) && row_names_.empty()) - { - throw std::runtime_error("[gctl::dsv_io::save_text] Row/Column names not instored."); - } - std::ofstream outfile; open_outfile(outfile, filename, file_exten); @@ -230,22 +184,8 @@ void gctl::dsv_io::save_text(std::string filename, std::string file_exten, table outfile << "# " << annotates_[i] << std::endl; } - if (t == BothHead) outfile << corner_name_ << deli_sym_; - - if (t == ColumnHead || t == BothHead) - { - outfile << col_names_[0]; - for (size_t j = 1; j < col_names_.size(); j++) - { - outfile << deli_sym_ << col_names_[j]; - } - outfile << std::endl; - } - for (int i = 0; i < row_num_; i++) { - if (t == RowHead || t == BothHead) outfile << row_names_[i] << deli_sym_; - outfile << table_[i][0].str_; for (size_t j = 1; j < col_num_; j++) { @@ -253,15 +193,14 @@ void gctl::dsv_io::save_text(std::string filename, std::string file_exten, table } outfile << std::endl; } - outfile.close(); return; } -void gctl::dsv_io::save_csv(std::string filename, table_headtype_e t) +void gctl::dsv_io::save_csv(std::string filename) { set_delimeter(','); - save_text(filename, ".csv", t); + save_text(filename, ".csv"); return; } @@ -269,6 +208,7 @@ void gctl::dsv_io::init_table(int row, int col, table_headtype_e t) { row_num_ = row; col_num_ = col; + thead_ = t; table_.resize(row_num_); for (size_t i = 0; i < row_num_; i++) @@ -282,21 +222,24 @@ void gctl::dsv_io::init_table(int row, int col, table_headtype_e t) if (t == RowHead || t == BothHead) { - row_names_.resize(row_num_); for (size_t i = 0; i < row_num_; i++) { - row_names_[i] = "row-" + std::to_string(i + 1); + table_[i][0].str_ = "row-" + std::to_string(i); } } if (t == ColumnHead || t == BothHead) { - col_names_.resize(col_num_); for (size_t i = 0; i < col_num_; i++) { - col_names_[i] = "col-" + std::to_string(i + 1); + table_[0][i].str_ = "col-" + std::to_string(i); } } + + if (t == BothHead) + { + table_[0][0].str_ = "row-idx"; + } return; } @@ -319,63 +262,60 @@ void gctl::dsv_io::set_tags(const std::vector &tags) return; } -void gctl::dsv_io::set_column_names(const std::vector &names) -{ - if (col_num_ != names.size()) - { - throw std::runtime_error("[gctl::dsv_io::set_column_names] Invalid name size."); - } - - col_names_ = names; - return; -} - -void gctl::dsv_io::set_row_names(const std::vector &names) -{ - if (row_num_ != names.size()) - { - throw std::runtime_error("[gctl::dsv_io::set_column_names] Invalid name size."); - } - - row_names_ = names; - return; -} - -void gctl::dsv_io::cell(int r, int c, double d, int p) -{ - std::stringstream ss; - if (p != 6) ss.precision(p); - - ss << d; - ss >> table_[r][c].str_; - return; -} - void gctl::dsv_io::info() { std::clog << "File: " << file_ << "\n------------\n"; std::clog << "Head(s): " << head_num_ << "\n"; std::clog << "Annotation(s): " << annotates_.size() << "\n"; std::clog << "Tag(s): " << tags_.size() << "\n"; - std::clog << "------------\nColumns:\n============\n"; + std::clog << "------------\n"; - if (col_names_.empty()) + if (thead_ == ColumnHead || thead_ == BothHead) { - for (size_t i = 0; i < col_num_; i++) + std::clog << "Columns: "; + std::clog << table_[0][0].str_; + for (size_t i = 1; i < col_num_; i++) { - std::clog << table_[0][i].str_ << " -> " << table_.back()[i].str_ << "\n"; + std::clog << "," << table_[0][i].str_; } + std::clog << "\n============" << std::endl; } - else + + if (thead_ == RowHead || thead_ == BothHead) { - for (size_t i = 0; i < col_num_; i++) + std::clog << "Rows: "; + std::clog << table_[0][0].str_; + for (size_t i = 1; i < row_num_; i++) { - std::clog << col_names_[i] << ": " << table_[0][i].str_ << " -> " << table_.back()[i].str_ << "\n"; + std::clog << "," << table_[i][0].str_; } + std::clog << "\n============" << std::endl; } return; } +gctl::geodsv_io::geodsv_io() : dsv_io::dsv_io(){} + +gctl::geodsv_io::~geodsv_io() +{ + dsv_io::~dsv_io(); +} + +gctl::geodsv_io::geodsv_io(std::string filename, std::string file_exten, table_headtype_e t) +{ + file_ = ""; + att_sym_ = '#'; + tag_sym_ = '!'; + deli_sym_ = ' '; + head_num_ = 0; + row_num_ = 0; + col_num_ = 0; + thead_ = ColumnHead; + + if (file_exten == ".csv") load_csv(filename, t); + else load_text(filename, file_exten, t); +} + void gctl::geodsv_io::fill_column_point2dc(int xid, int yid, const array &data, int p) { if (xid >= col_num_ || yid >= col_num_ || xid == yid) diff --git a/lib/io/dsv_io.h b/lib/io/dsv_io.h index bb38c17..9585595 100644 --- a/lib/io/dsv_io.h +++ b/lib/io/dsv_io.h @@ -50,9 +50,17 @@ namespace gctl } } - template void value(const T &in) + template void value(const T &in, int p = 6) { - str_ = std::to_string(in); + // 对于double类型 可以设置转换的有效数字位数(精度) + if constexpr (std::is_same::value) + { + std::stringstream ss; + ss.precision(p); + ss << in; + ss >> str_; + } + else str_ = std::to_string(in); return; } }; @@ -83,16 +91,15 @@ namespace gctl class dsv_io { protected: - std::string file_, corner_name_; + std::string file_; + table_headtype_e thead_; // 头信息行数 表格行数 表格列数 int head_num_, row_num_, col_num_; // 注释行起始符 标记行起始符 分割符 char att_sym_, tag_sym_, deli_sym_; // 头信息行 注释行 标记行 std::vector heads_, annotates_, tags_; - // 内容行与表格 - std::vector col_names_, row_names_; - std::vector lines_; + // 内容表格 std::vector > table_; public: @@ -165,15 +172,6 @@ namespace gctl */ int col_number(){return col_num_;} - /** - * @brief 返回行数据 - * - * @note 目前只有load_text函数才会使用lines - * - * @return 返回按行储存的文本内容 - */ - const std::vector& get_lines(){return lines_;} - /** * @brief 返回头信息 * @@ -195,20 +193,6 @@ namespace gctl */ const std::vector& get_tags(){return tags_;} - /** - * @brief 返回列名称 - * - * @return 列名称 - */ - const std::vector& get_column_names(){return col_names_;} - - /** - * @brief 返回行名称 - * - * @return 行名称 - */ - const std::vector& get_row_names(){return row_names_;} - /** * @brief 设置头信息 * @@ -230,20 +214,6 @@ namespace gctl */ void set_tags(const std::vector &tags); - /** - * @brief 设置列数据名称 - * - * @param names 列名称 - */ - void set_column_names(const std::vector &names); - - /** - * @brief 设置行数据名称 - * - * @param names 行名称 - */ - void set_row_names(const std::vector &names); - /** * @brief 清理字符串向量对象 * @@ -271,14 +241,14 @@ namespace gctl * @param filename 文件名 * @param file_exten 文件扩展名 */ - void save_text(std::string filename, std::string file_exten = ".txt", table_headtype_e t = NoHead); + void save_text(std::string filename, std::string file_exten = ".txt"); /** * @brief 将内容写入CSV文件 * * @param filename 文件名(无后缀) */ - void save_csv(std::string filename, table_headtype_e t = ColumnHead); + void save_csv(std::string filename); /** * @brief 初始化表格 @@ -288,6 +258,12 @@ namespace gctl */ void init_table(int row, int col, table_headtype_e t = ColumnHead); + /** + * @brief 返回表格信息 + * + */ + void info(); + /** * @brief 填充列 * @@ -378,23 +354,7 @@ namespace gctl * @param c 列号 * @param d 数据 */ - template void cell(int r, int c, T d){table_[r][c].value(d); return;} - - /** - * @brief 填充表格单元数据 double类型专用 - * - * @param r 行号 - * @param c 列号 - * @param d 数据 - * @param p 有效数字位数 - */ - void cell(int r, int c, double d, int p); - - /** - * @brief 返回表格信息 - * - */ - void info(); + template void cell(int r, int c, T d, int p = 6){table_[r][c].value(d, p); return;} }; template @@ -404,44 +364,28 @@ namespace gctl { throw std::runtime_error("[gctl::dsv_io::fill_column] Invalid column index."); } - - if constexpr (std::is_same::value) - { - std::string s; - std::stringstream ss; - ss.precision(p); - - for (size_t i = 0; i < std::min(row_num_, data.size()); i++) - { - ss.clear(); - ss << data[i]; - ss >> s; - table_[i][idx].str_ = s; - } - } - else - { - for (size_t i = 0; i < std::min(row_num_, data.size()); i++) - { - table_[i][idx].value(data[i]); - } - } + int st = 0; + if (thead_ == ColumnHead || thead_ == BothHead) st = 1; + for (size_t i = st; i < std::min(row_num_, data.size()); i++) + { + table_[i][idx].value(data[i - st], p); + } return; } template void dsv_io::fill_column(std::string name, const array &data, int p) { - if (col_names_.empty()) + if (thead_ != ColumnHead && thead_ != BothHead) { - throw std::runtime_error("[gctl::dsv_io::fill_column] No column names instored."); + throw std::runtime_error("[gctl::dsv_io::fill_column] The table is initialized with no column names."); } - for (size_t i = 0; i < col_names_.size(); i++) + for (size_t i = 0; i < col_num_; i++) { - if (col_names_[i] == name) + if (table_[0][i].str_ == name) { fill_column(i, data, p); return; @@ -460,26 +404,12 @@ namespace gctl throw std::runtime_error("[gctl::dsv_io::fill_row] Invalid row index."); } - if constexpr (std::is_same::value) - { - std::string s; - std::stringstream ss; - ss.precision(p); + int st = 0; + if (thead_ == RowHead || thead_ == BothHead) st = 1; - for (size_t i = 0; i < std::min(col_num_, data.size()); i++) - { - ss.clear(); - ss << data[i]; - ss >> s; - table_[idx][i].str_ = s; - } - } - else + for (size_t i = st; i < std::min(col_num_, data.size()); i++) { - for (size_t i = 0; i < std::min(col_num_, data.size()); i++) - { - table_[idx][i].value(data[i]); - } + table_[idx][i].value(data[i - st], p); } return; } @@ -487,14 +417,14 @@ namespace gctl template void dsv_io::fill_row(std::string name, const array &data, int p) { - if (row_names_.empty()) + if (thead_ != RowHead && thead_ != BothHead) { - throw std::runtime_error("[gctl::dsv_io::fill_row] No row names instored."); + throw std::runtime_error("[gctl::dsv_io::fill_row] The table is initialized with no row names."); } - for (size_t i = 0; i < row_names_.size(); i++) + for (size_t i = 0; i < row_num_; i++) { - if (row_names_[i] == name) + if (table_[i][0].str_ == name) { fill_row(i, data, p); return; @@ -512,11 +442,14 @@ namespace gctl { throw std::runtime_error("[gctl::dsv_io::get_column] Invalid column index."); } - - data.resize(row_num_); - for (size_t i = 0; i < row_num_; i++) - { - data[i] = table_[i][idx].value(); + + int st = 0; + if (thead_ == ColumnHead || thead_ == BothHead) st = 1; + + data.resize(row_num_ - st); + for (size_t i = st; i < row_num_; i++) + { + data[i - st] = table_[i][idx].value(); } return; } @@ -524,14 +457,14 @@ namespace gctl template void dsv_io::get_column(std::string name, array &data) { - if (col_names_.empty()) + if (thead_ != ColumnHead && thead_ != BothHead) { - throw std::runtime_error("[gctl::dsv_io::get_column] No column names instored."); + throw std::runtime_error("[gctl::dsv_io::get_column] The table is initialized with no column names."); } - for (size_t i = 0; i < col_names_.size(); i++) + for (size_t i = 0; i < col_num_; i++) { - if (col_names_[i] == name) + if (table_[0][i].str_ == name) { get_column(i, data); return; @@ -550,10 +483,13 @@ namespace gctl throw std::runtime_error("[gctl::dsv_io::get_row] Invalid row index."); } - data.resize(col_num_); - for (size_t i = 0; i < col_num_; i++) - { - data[i] = table_[idx][i].value(); + int st = 0; + if (thead_ == RowHead || thead_ == BothHead) st = 1; + + data.resize(col_num_ - st); + for (size_t i = st; i < col_num_; i++) + { + data[i - st] = table_[idx][i].value(); } return; } @@ -561,14 +497,14 @@ namespace gctl template void dsv_io::get_row(std::string name, array &data) { - if (row_names_.empty()) + if (thead_ != RowHead && thead_ != BothHead) { - throw std::runtime_error("[gctl::dsv_io::get_row] No row names instored."); + throw std::runtime_error("[gctl::dsv_io::get_row] The table is initialized with no row names."); } - for (size_t i = 0; i < row_names_.size(); i++) + for (size_t i = 0; i < row_num_; i++) { - if (row_names_[i] == name) + if (table_[i][0].str_ == name) { get_row(i, data); return; @@ -582,8 +518,16 @@ namespace gctl class geodsv_io : public dsv_io { public: - geodsv_io(){}; - ~geodsv_io(){}; + geodsv_io(); + ~geodsv_io(); + + /** + * @brief Construct a new text descriptor object and load text file + * + * @param filename 文件名 + * @param file_exten 文件扩展名 + */ + geodsv_io(std::string filename, std::string file_exten = ".txt", table_headtype_e t = NoHead); void fill_column_point2dc(int xid, int yid, const array &data, int p = 6);