diff --git a/Applications/FileIO/CsvInterface.cpp b/Applications/FileIO/CsvInterface.cpp index b508181b095acd3e388d0007d19e4ab6160083c1..f5850fb3103ac612c6d4b8b80c2151e6c6fc0b2b 100644 --- a/Applications/FileIO/CsvInterface.cpp +++ b/Applications/FileIO/CsvInterface.cpp @@ -22,6 +22,39 @@ namespace FileIO { CsvInterface::CsvInterface() = default; +std::vector<std::string> CsvInterface::getColumnNames(std::string const& fname, + char const delim) +{ + std::ifstream in(fname.c_str()); + + if (!in.is_open()) + { + ERR("CsvInterface::readPoints(): Could not open file %s.", + fname.c_str()); + return std::vector<std::string>(); + } + std::string line; + if (!getline(in, line)) + return {}; + + std::list<std::string> fields; + if (delim != '\n') + fields = BaseLib::splitString(line, delim); + + if (fields.size() < 2) + { + for (char const d : {'\t', ';', ','}) + { + fields = BaseLib::splitString(line, d); + if (fields.size() > 1) + { + break; + } + } + } + return {begin(fields), end(fields)}; +} + int CsvInterface::readPoints(std::string const& fname, char delim, std::vector<GeoLib::Point*> &points) { diff --git a/Applications/FileIO/CsvInterface.h b/Applications/FileIO/CsvInterface.h index b2e0bdd62417290c640a4a95ba2ffd7136030aeb..779d7de4a60d608f52f911e2b49d74af3f161258 100644 --- a/Applications/FileIO/CsvInterface.h +++ b/Applications/FileIO/CsvInterface.h @@ -48,6 +48,11 @@ public: /// Returns the number of vectors currently staged for writing. std::size_t getNArrays() const { return _vec_names.size(); } + /// Returns a vector containing the names of columns in the file (assuming + /// the file *has* a header) + static std::vector<std::string> getColumnNames(std::string const& fname, + char delim); + /// Adds an index vector of size s to the CSV file void addIndexVectorForWriting(std::size_t s); diff --git a/Tests/FileIO/TestCsvReader.cpp b/Tests/FileIO/TestCsvReader.cpp index fd12ecb4dacfe85aa0290030b56cc33bb0b0e144..2d36985717030c837e6ce0867138bb6380cc2078 100644 --- a/Tests/FileIO/TestCsvReader.cpp +++ b/Tests/FileIO/TestCsvReader.cpp @@ -168,15 +168,20 @@ TEST_F(CsvInterfaceTest, CoordinateOrder) /// Getting single columns TEST_F(CsvInterfaceTest, GetColumn) { + std::vector<std::string> columns = + FileIO::CsvInterface::getColumnNames(_file_name, '\t'); + ASSERT_EQ(7, columns.size()); std::vector<std::string> names; - _result = FileIO::CsvInterface::readColumn<std::string>(_file_name, '\t', names, "name"); + _result = FileIO::CsvInterface::readColumn<std::string>(_file_name, '\t', names, columns[4]); ASSERT_EQ(0, _result); ASSERT_EQ(10, names.size()); + ASSERT_EQ("test_j", names[9]); std::vector<double> values; - _result = FileIO::CsvInterface::readColumn<double>(_file_name, '\t', values, "value_two"); + _result = FileIO::CsvInterface::readColumn<double>(_file_name, '\t', values, columns[6]); ASSERT_EQ(2, _result); ASSERT_EQ(8, values.size()); + ASSERT_NEAR(135, values[1], std::numeric_limits<double>::epsilon()); } /// Dealing with non-existing column