OGS
CsvInterface.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <any>
17 #include <array>
18 #include <fstream>
19 #include <iterator>
20 #include <limits>
21 #include <list>
22 #include <string>
23 #include <typeinfo>
24 #include <vector>
25 
26 #include "BaseLib/IO/Writer.h"
27 #include "BaseLib/Logging.h"
28 #include "BaseLib/StringTools.h"
29 
30 namespace GeoLib
31 {
32 class Point;
33 }
34 
35 namespace FileIO
36 {
41 {
42 public:
45 
47  std::size_t getNArrays() const { return _vec_names.size(); }
48 
51  static std::vector<std::string> getColumnNames(std::string const& fname,
52  char delim);
53 
55  void addIndexVectorForWriting(std::size_t s);
56 
58  void setCsvHeader(bool write_header) { _writeCsvHeader = write_header; }
59 
63  template <typename T>
64  bool addVectorForWriting(std::string const& vec_name,
65  std::vector<T> const& vec)
66  {
67  static_assert(
68  std::is_same_v<T, std::string> || std::is_same_v<T, double> ||
69  std::is_same_v<T, int>,
70  "CsvInterface can only write vectors of strings, doubles or ints.");
71 
72  if (!_data.empty())
73  {
74  std::size_t const vec_size(getVectorSize(0));
75  if (vec_size != vec.size())
76  {
77  ERR("Vector size does not match existing data (should be "
78  "{:d}).",
79  vec_size);
80  return false;
81  }
82  }
83 
84  _vec_names.push_back(vec_name);
85  _data.push_back(vec);
86  return true;
87  }
88 
90  bool write() override;
91 
101  static int readPoints(std::string const& fname, char delim,
102  std::vector<GeoLib::Point*>& points);
103 
119  static int readPoints(std::string const& fname, char delim,
120  std::vector<GeoLib::Point*>& points,
121  std::string const& x_column_name,
122  std::string const& y_column_name,
123  std::string const& z_column_name = "");
124 
139  static int readPoints(
140  std::string const& fname, char delim,
141  std::vector<GeoLib::Point*>& points, std::size_t x_column_idx,
142  std::size_t y_column_idx,
143  std::size_t z_column_idx = std::numeric_limits<std::size_t>::max());
144 
154  template <typename T>
155  static int readColumn(std::string const& fname, char delim,
156  std::vector<T>& data_array,
157  std::string const& column_name)
158  {
159  std::ifstream in(fname.c_str());
160  if (!in.is_open())
161  {
162  ERR("CsvInterface::readColumn(): Could not open file {:s}.", fname);
163  return -1;
164  }
165 
166  std::string line;
167  std::getline(in, line);
168  std::size_t const column_idx =
169  CsvInterface::findColumn(line, delim, column_name);
170  if (column_idx == std::numeric_limits<std::size_t>::max())
171  {
172  ERR("Column '{:s}' not found in file header.", column_name);
173  return -1;
174  }
175  return readColumn<T>(in, delim, data_array, column_idx);
176  }
177 
178  template <typename T>
179  static int readColumn(std::string const& fname, char delim,
180  std::vector<T>& data_array, std::size_t column_idx)
181  {
182  std::ifstream in(fname.c_str());
183  if (!in.is_open())
184  {
185  ERR("CsvInterface::readColumn(): Could not open file {:s}.", fname);
186  return -1;
187  }
188  return readColumn<T>(in, delim, data_array, column_idx);
189  }
190 
191 private:
193  static int readPoints(std::ifstream& in, char delim,
194  std::vector<GeoLib::Point*>& points,
195  std::array<std::size_t, 3> const& column_idx);
196 
198  template <typename T>
199  static int readColumn(std::ifstream& in, char delim,
200  std::vector<T>& data_array, std::size_t column_idx)
201  {
202  std::string line;
203  std::size_t line_count(0);
204  std::size_t error_count(0);
205  while (std::getline(in, line))
206  {
207  line_count++;
208  std::list<std::string> const fields =
209  BaseLib::splitString(line, delim);
210 
211  if (fields.size() < column_idx + 1)
212  {
213  ERR("Line {:d} contains not enough columns of data. Skipping "
214  "line...",
215  line_count);
216  error_count++;
217  continue;
218  }
219  auto it = fields.begin();
220  std::advance(it, column_idx);
221 
222  std::istringstream stream(*it);
223  T value;
224  if (!(stream >> value))
225  {
226  ERR("Error reading value in line {:d}.", line_count);
227  error_count++;
228  continue;
229  }
230 
231  data_array.push_back(value);
232  }
233  return error_count;
234  }
235 
238  static std::size_t findColumn(std::string const& line, char delim,
239  std::string const& column_name);
240 
242  std::size_t getVectorSize(std::size_t idx) const;
243 
249  void writeValue(std::size_t vec_idx, std::size_t in_vec_idx);
250 
251  bool _writeCsvHeader{true};
252  std::vector<std::string> _vec_names;
253  std::vector<std::any> _data;
254 };
255 
256 } // namespace FileIO
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
Definition of string helper functions.
Definition of the Writer class.
Base class which enables writing an object to string, stringstream or file.
Definition: Writer.h:31
static int readColumn(std::ifstream &in, char delim, std::vector< T > &data_array, std::size_t column_idx)
Actual column reader for public methods.
Definition: CsvInterface.h:199
std::vector< std::any > _data
Definition: CsvInterface.h:253
void writeValue(std::size_t vec_idx, std::size_t in_vec_idx)
std::vector< std::string > _vec_names
Definition: CsvInterface.h:252
static std::vector< std::string > getColumnNames(std::string const &fname, char delim)
bool addVectorForWriting(std::string const &vec_name, std::vector< T > const &vec)
Definition: CsvInterface.h:64
void setCsvHeader(bool write_header)
Stores if the CSV file to be written should include a header or not.
Definition: CsvInterface.h:58
static std::size_t findColumn(std::string const &line, char delim, std::string const &column_name)
static int readColumn(std::string const &fname, char delim, std::vector< T > &data_array, std::size_t column_idx)
Definition: CsvInterface.h:179
void addIndexVectorForWriting(std::size_t s)
Adds an index vector of size s to the CSV file.
static int readColumn(std::string const &fname, char delim, std::vector< T > &data_array, std::string const &column_name)
Definition: CsvInterface.h:155
std::size_t getVectorSize(std::size_t idx) const
Returns the size of the vector with the given index.
std::size_t getNArrays() const
Returns the number of vectors currently staged for writing.
Definition: CsvInterface.h:47
CsvInterface()
Constructor (only needed for writing files)
bool write() override
Writes the CSV file.
static int readPoints(std::string const &fname, char delim, std::vector< GeoLib::Point * > &points)
std::vector< std::string > splitString(std::string const &str)
Definition: StringTools.cpp:28
TemplateElement< PointRule1 > Point
Definition: Point.h:20