CSV.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2016-2019 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "CSV.H"
30 #include "DynamicList.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 template<>
36 (
37  const List<string>& splitted
38 ) const
39 {
40  if (componentColumns_[0] >= splitted.size())
41  {
43  << "No column " << componentColumns_[0] << " in "
44  << splitted << endl
45  << exit(FatalError);
46  }
47 
48  return readLabel(splitted[componentColumns_[0]]);
49 }
50 
51 
52 template<>
54 (
55  const List<string>& splitted
56 ) const
57 {
58  if (componentColumns_[0] >= splitted.size())
59  {
61  << "No column " << componentColumns_[0] << " in "
62  << splitted << endl
63  << exit(FatalError);
64  }
65 
66  return readScalar(splitted[componentColumns_[0]]);
67 }
68 
69 
70 template<class Type>
72 (
73  const List<string>& splitted
74 ) const
75 {
76  Type result;
77 
78  for (label i = 0; i < pTraits<Type>::nComponents; ++i)
79  {
80  if (componentColumns_[i] >= splitted.size())
81  {
83  << "No column " << componentColumns_[i] << " in "
84  << splitted << endl
85  << exit(FatalError);
86  }
87 
88  result[i] = readScalar(splitted[componentColumns_[i]]);
89  }
90 
91  return result;
92 }
93 
94 
95 template<class Type>
97 {
98  fileName expandedFile(fName_);
99  autoPtr<ISstream> isPtr(fileHandler().NewIFstream(expandedFile.expand()));
100  ISstream& is = isPtr();
101 
102  if (!is.good())
103  {
105  << "Cannot open CSV file for reading."
106  << exit(FatalIOError);
107  }
108 
109  DynamicList<Tuple2<scalar, Type>> values;
110 
111  // skip header
112  for (label i = 0; i < nHeaderLine_; i++)
113  {
114  string line;
115  is.getLine(line);
116  }
117 
118  label nEntries = max(componentColumns_);
119 
120  // read data
121  while (is.good())
122  {
123  string line;
124  is.getLine(line);
125 
126 
127  label n = 0;
128  std::size_t pos = 0;
129  DynamicList<string> splitted;
130 
131  if (mergeSeparators_)
132  {
133  std::size_t nPos = 0;
134 
135  while ((pos != std::string::npos) && (n <= nEntries))
136  {
137  bool found = false;
138  while (!found)
139  {
140  nPos = line.find(separator_, pos);
141 
142  if ((nPos != std::string::npos) && (nPos - pos == 0))
143  {
144  pos = nPos + 1;
145  }
146  else
147  {
148  found = true;
149  }
150  }
151 
152  nPos = line.find(separator_, pos);
153 
154  if (nPos == std::string::npos)
155  {
156  splitted.append(line.substr(pos));
157  pos = nPos;
158  n++;
159  }
160  else
161  {
162  splitted.append(line.substr(pos, nPos - pos));
163  pos = nPos + 1;
164  n++;
165  }
166  }
167  }
168  else
169  {
170  while ((pos != std::string::npos) && (n <= nEntries))
171  {
172  std::size_t nPos = line.find(separator_, pos);
173 
174  if (nPos == std::string::npos)
175  {
176  splitted.append(line.substr(pos));
177  pos = nPos;
178  n++;
179  }
180  else
181  {
182  splitted.append(line.substr(pos, nPos - pos));
183  pos = nPos + 1;
184  n++;
185  }
186  }
187  }
188 
189 
190  if (splitted.size() <= 1)
191  {
192  break;
193  }
194 
195  scalar x = readScalar(splitted[refColumn_]);
196  Type value = readValue(splitted);
197 
198  values.append(Tuple2<scalar,Type>(x, value));
199  }
200 
201  this->table_.transfer(values);
202 }
203 
204 
205 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
206 
207 template<class Type>
209 (
210  const word& entryName,
211  const dictionary& dict,
212  const fileName& fName
213 )
214 :
215  TableBase<Type>(entryName, dict),
216  nHeaderLine_(dict.get<label>("nHeaderLine")),
217  refColumn_(dict.get<label>("refColumn")),
218  componentColumns_(),
219  separator_(dict.getOrDefault<string>("separator", ",")[0]),
220  mergeSeparators_(dict.get<bool>("mergeSeparators")),
221  fName_(fName.empty() ? dict.get<fileName>("file") : fName)
222 {
223  // Writing of "componentColumns" was forced to be ASCII,
224  // do the same when reading
225  ITstream& is = dict.lookup("componentColumns");
226  is.format(IOstream::ASCII);
227  is >> componentColumns_;
228  dict.checkITstream(is, "componentColumns");
229 
230  if (componentColumns_.size() != pTraits<Type>::nComponents)
231  {
233  << componentColumns_ << " does not have the expected length of "
235  << exit(FatalIOError);
236  }
237 
238  read();
239 
241 }
242 
243 
244 template<class Type>
246 :
247  TableBase<Type>(csv),
248  nHeaderLine_(csv.nHeaderLine_),
249  refColumn_(csv.refColumn_),
250  componentColumns_(csv.componentColumns_),
251  separator_(csv.separator_),
252  mergeSeparators_(csv.mergeSeparators_),
253  fName_(csv.fName_)
254 {}
255 
256 
257 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
258 
259 template<class Type>
261 {
262  return fName_;
263 }
264 
265 
266 template<class Type>
268 {
270  os.endEntry();
271 
272  os.beginBlock(word(this->name() + "Coeffs"));
273 
274  // Note: for TableBase write the dictionary entries it needs but not
275  // the values themselves
277 
278  os.writeEntry("nHeaderLine", nHeaderLine_);
279  os.writeEntry("refColumn", refColumn_);
280 
281  // Force writing labelList in ascii
282  const enum IOstream::streamFormat fmt = os.format();
284  os.writeEntry("componentColumns", componentColumns_);
285  os.format(fmt);
286 
287  os.writeEntry("separator", string(separator_));
288  os.writeEntry("mergeSeparators", mergeSeparators_);
289  os.writeEntry("file", fName_);
290 
291  os.endBlock();
292 }
293 
294 
295 // ************************************************************************* //
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::HashTableOps::values
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:149
Foam::Function1Types::CSV
Templated CSV function.
Definition: CSV.H:76
Foam::IOstreamOption::format
streamFormat format() const noexcept
Get the current stream format.
Definition: IOstreamOption.H:273
Foam::fileHandler
const fileOperation & fileHandler()
Get current file handler.
Definition: fileOperation.C:1181
Foam::Function1Types::CSV::CSV
CSV(const word &entryName, const dictionary &dict, const fileName &fName=fileName::null)
Construct from entry name and dictionary.
Definition: CSV.C:209
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::Ostream::beginBlock
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
Definition: Ostream.C:91
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::ITstream
An input stream of tokens.
Definition: ITstream.H:55
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::Function1Types::CSV::writeData
virtual void writeData(Ostream &os) const
Write in dictionary format.
Definition: CSV.C:267
Foam::Function1::writeData
virtual void writeData(Ostream &os) const
Write in dictionary format.
Definition: Function1.C:165
Foam::Ostream::endEntry
virtual Ostream & endEntry()
Write end entry (';') followed by newline.
Definition: Ostream.C:118
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::blockMeshTools::read
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:33
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::Ostream::endBlock
virtual Ostream & endBlock()
Write end block group.
Definition: Ostream.C:109
Foam::IOstreamOption::streamFormat
streamFormat
Data format (ascii | binary)
Definition: IOstreamOption.H:64
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::IOstreamOption::ASCII
"ascii"
Definition: IOstreamOption.H:66
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
CSV.H
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::readLabel
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:70
Foam::pTraits
Traits class for primitives.
Definition: pTraits.H:52
Foam::Function1Types::TableBase::writeEntries
virtual void writeEntries(Ostream &os) const
Write keywords only in dictionary format.
Definition: TableBase.C:349
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:219
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:375
DynamicList.H
Foam::Function1Types::TableBase
Base class for table with bounds handling, interpolation and integration.
Definition: TableBase.H:58
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::Function1Types::CSV::fName
virtual const fileName & fName() const
Return const access to the file name.
Definition: CSV.C:260
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177