gctl/lib/io/text_io2.h
2024-12-13 10:11:47 +08:00

469 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************
* ██████╗ ██████╗████████╗██╗
* ██╔════╝ ██╔════╝╚══██╔══╝██║
* ██║ ███╗██║ ██║ ██║
* ██║ ██║██║ ██║ ██║
* ╚██████╔╝╚██████╗ ██║ ███████╗
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
* Geophysical Computational Tools & Library (GCTL)
*
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
*
* GCTL is distributed under a dual licensing scheme. You can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 2
* of the License, or (at your option) any later version. You should have
* received a copy of the GNU Lesser General Public License along with this
* program. If not, see <http://www.gnu.org/licenses/>.
*
* If the terms and conditions of the LGPL v.2. would prevent you from using
* the GCTL, please consider the option to obtain a commercial license for a
* fee. These licenses are offered by the GCTL's original author. As a rule,
* licenses are provided "as-is", unlimited in time for a one time fee. Please
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
* to include some description of your company and the realm of its activities.
* Also add information on how to contact you by electronic and paper mail.
******************************************************/
#ifndef _GCTL_TEXT_IO2_H
#define _GCTL_TEXT_IO2_H
#include "../core.h"
#include "../utility.h"
namespace gctl
{
struct cell_content
{
std::string str_;
template <typename T> T value()
{
T out;
str2type(str_, out);
return out;
}
template <typename T> void value(const T &in)
{
str_ = std::to_string(in);
return;
}
};
enum text_head_type_e
{
HasColumnName,
NoColumnName,
};
/**
* @brief 文本读写类
*
* 可以处理的文本数据应该符合下述要求:
* 1. 以'#'开始的行均为注释行,标识符可由用户指定;
* 2. 以'#!'开始的行均为标记行,标识符可由用户指定;
* 3. 文本开始可以包含n行头信息
* 4. 数据体为一个row*col大小的表格。
*
*/
class text_content
{
private:
std::string file_;
// 头信息行数 表格行数 表格列数
int head_num_, row_num_, col_num_;
// 注释行起始符 标记行起始符 分割符
char att_sym_, tag_sym_, deli_sym_;
// 头信息行 注释行 标记行
std::vector<std::string> heads_, annotates_, tags_;
// 内容行与表格
std::vector<std::string> col_names_;
std::vector<std::string> lines_;
std::vector<std::vector<cell_content> > table_;
public:
/**
* @brief Construct a new text content object
*
*/
text_content();
/**
* @brief Destroy the text content object
*
*/
~text_content();
/**
* @brief Construct a new text descriptor object and load text file
*
* @param filename 文件名
* @param file_exten 文件扩展名
*/
text_content(std::string filename, std::string file_exten = ".txt", text_head_type_e t = NoColumnName);
/**
* @brief 设置列分隔符
*
* @param deli_sym 分隔符
*/
void set_delimeter(char deli_sym){deli_sym_ = deli_sym;}
/**
* @brief 设置头信息行数
*
* @param num 行数
*/
void set_head_number(char num){head_num_ = num;}
/**
* @brief 设置注释行符号
*
* @param att_sym 注释符号
*/
void set_annotation_symbol(char att_sym){att_sym_ = att_sym;}
/**
* @brief 设置标记行符号
*
* @param tag_sym 标记符号
*/
void set_tag_symbol(char tag_sym){tag_sym_ = tag_sym;}
/**
* @brief 返回头信息行数
*
* @return 行数
*/
int head_number(){return head_num_;}
/**
* @brief 返回行数
*
* @return 行数
*/
int row_number(){return row_num_;}
/**
* @brief 返回列数
*
* @return 列数
*/
int col_number(){return col_num_;}
/**
* @brief 返回行数据
*
* @note 目前只有load_text函数才会使用lines
*
* @return 返回按行储存的文本内容
*/
const std::vector<std::string>& get_lines(){return lines_;}
/**
* @brief 返回头信息
*
* @return 头信息
*/
const std::vector<std::string>& get_head_records(){return heads_;}
/**
* @brief 返回注释行
*
* @return 注释行
*/
const std::vector<std::string>& get_annotoations(){return annotates_;}
/**
* @brief 返回标记行
*
* @return 标记
*/
const std::vector<std::string>& get_tags(){return tags_;}
/**
* @brief 返回列名称
*
* @return 列名称
*/
const std::vector<std::string>& get_column_names(){return col_names_;}
/**
* @brief 设置头信息
*
* @param heads 头信息
*/
void set_head_records(const std::vector<std::string> &heads);
/**
* @brief 设置注释
*
* @param att 注释
*/
void set_annotoations(const std::vector<std::string> &att);
/**
* @brief 设置标记
*
* @param tags 标记
*/
void set_tags(const std::vector<std::string> &tags);
/**
* @brief 设置列数据名称
*
* @param names 列名称
*/
void set_column_names(const std::vector<std::string> &names);
/**
* @brief 清理字符串向量对象
*
*/
void clear();
/**
* @brief 读入文本文件
*
* @param filename 文件名
* @param file_exten 文件扩展名
*/
void load_text(std::string filename, std::string file_exten = ".txt", text_head_type_e t = NoColumnName);
/**
* @brief 读入CSV文件
*
* @param filename 文件名
*/
void load_csv(std::string filename, text_head_type_e t = HasColumnName);
/**
* @brief 将内容写入文件
*
* @param filename 文件名
* @param file_exten 文件扩展名
*/
void save_text(std::string filename, std::string file_exten = ".txt");
/**
* @brief 将内容写入CSV文件
*
* @param filename 文件名(无后缀)
*/
void save_csv(std::string filename);
/**
* @brief 初始化表格
*
* @param row 行数
* @param col 列数
*/
void init_table(int row, int col);
/**
* @brief 初始化表格
*
* @param row 行数
* @param col 列数
* @param names 列名称
*/
void init_table(int row, int col, const std::vector<std::string> &names);
/**
* @brief 填充列
*
* @tparam T 数据类型
* @param idx 列索引
* @param data 列数据
*/
template <typename T> void fill_column(int idx, const array<T> &data);
/**
* @brief 填充列
*
* @tparam T 数据类型
* @param name 列名称
* @param data 列数据
*/
template <typename T> void fill_column(std::string name, const array<T> &data);
/**
* @brief 填充行
*
* @tparam T 数据类型
* @param idx 行索引
* @param data 行数据
*/
template <typename T> void fill_row(int idx, const array<T> &data);
/**
* @brief 获取列数据
*
* @tparam T 数据类型
* @param idx 列索引
* @param data 列数据
*/
template <typename T> void get_column(int idx, array<T> &data);
/**
* @brief 获取列数据
*
* @tparam T 数据类型
* @param name 列名称
* @param data 列数据
*/
template <typename T> void get_column(std::string name, array<T> &data);
/**
* @brief 获取行数据
*
* @tparam T 数据类型
* @param idx 行索引
* @param data 行数据
*/
template <typename T> void get_row(int idx, array<T> &data);
/**
* @brief 获取表格单元数据
*
* @tparam T 数据类型
* @param r 行号
* @param c 列号
* @return T 单元数据
*/
template <typename T> T cell(int r, int c){return table_[r][c].value<T>();}
/**
* @brief 填充表格单元数据
*
* @tparam T 数据类型
* @param r 行号
* @param c 列号
* @param d 数据
*/
template <typename T> 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 <typename T>
void text_content::fill_column(int idx, const array<T> &data)
{
if (idx >= col_num_)
{
throw std::runtime_error("[gctl::text_content::fill_column] Invalid column index.");
}
for (size_t i = 0; i < std::min(row_num_, data.size()); i++)
{
table_[i][idx].value(data[i]);
}
return;
}
template <typename T>
void text_content::fill_column(std::string name, const array<T> &data)
{
if (col_names_.empty())
{
throw std::runtime_error("[gctl::text_content::fill_column] No column names instored.");
}
for (size_t i = 0; i < col_names_.size(); i++)
{
if (col_names_[i] == name)
{
fill_column(i, data);
return;
}
}
throw std::runtime_error("[gctl::text_content::fill_column] No column found by the input name.");
return;
}
template <typename T>
void text_content::fill_row(int idx, const array<T> &data)
{
if (idx >= row_num_)
{
throw std::runtime_error("[gctl::text_content::fill_row] Invalid row index.");
}
for (size_t i = 0; i < std::min(col_num_, data.size()); i++)
{
table_[idx][i].value(data[i]);
}
return;
}
template <typename T>
void text_content::get_column(int idx, array<T> &data)
{
if (idx >= col_num_)
{
throw std::runtime_error("[gctl::text_content::get_column] Invalid column index.");
}
data.resize(row_num_);
for (size_t i = 0; i < row_num_; i++)
{
data[i] = table_[i][idx].value<T>();
}
return;
}
template <typename T>
void text_content::get_column(std::string name, array<T> &data)
{
if (col_names_.empty())
{
throw std::runtime_error("[gctl::text_content::get_column] No column names instored.");
}
for (size_t i = 0; i < col_names_.size(); i++)
{
if (col_names_[i] == name)
{
get_column(i, data);
return;
}
}
throw std::runtime_error("[gctl::text_content::get_column] No column found by the input name.");
return;
}
template <typename T>
void text_content::get_row(int idx, array<T> &data)
{
if (idx >= row_num_)
{
throw std::runtime_error("[gctl::text_content::get_column] Invalid row index.");
}
data.resize(col_num_);
for (size_t i = 0; i < col_num_; i++)
{
data[i] = table_[idx][i].value<T>();
}
return;
}
}
#endif //_GCTL_TEXT_IO2_H