Isis 3 Programmer Reference
TextFile.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "IException.h"
8 #include "IException.h"
9 #include "FileName.h"
10 #include "Message.h"
11 #include "TextFile.h"
12 #include "IString.h"
13 
14 #include <iostream>
15 
16 #include <QFileInfo>
17 
18 using namespace std;
19 namespace Isis {
20 
22  TextFile::TextFile() {
23  }
24 
41  TextFile::TextFile(const QString &filename,
42  const char *openmode, const char *extension) {
43  SetComment();
44  SetNewLine();
45  Open(filename, openmode, extension);
46  }
47 
72  TextFile::TextFile(const QString &filename, const char *openmode,
73  std::vector<QString> &lines, const int &maxLinesToReadWrite,
74  const bool skipComments) {
75  SetComment();
76  SetNewLine();
77  Open(filename, openmode);
78  if(p_openmode == 1) {
79  GetFile(lines, maxLinesToReadWrite, skipComments);
80  }
81  else {
82  PutFile(lines, maxLinesToReadWrite);
83  }
84  }
109  TextFile::TextFile(const char *filename, const char *openmode,
110  std::vector<QString> &lines, const int &maxLinesToReadWrite,
111  const bool skipComments) {
112  TextFile(QString(filename), openmode, lines, maxLinesToReadWrite, skipComments);
113  }
114 
140  TextFile::TextFile(const QString &filename, const char *openmode,
141  QString *lines, const int &maxLinesToReadWrite,
142  const bool skipComments) {
143  SetComment();
144  SetNewLine();
145  Open(filename, openmode);
146  if(p_openmode == 1) {
147  GetFile(lines, maxLinesToReadWrite, skipComments);
148  }
149  else {
150  PutFile(lines, maxLinesToReadWrite);
151  }
152  }
153 
178  TextFile::TextFile(const char *filename, const char *openmode,
179  QString *lines, const int &maxLinesToReadWrite,
180  const bool skipComments) {
181  TextFile(QString(filename), openmode, lines, maxLinesToReadWrite, skipComments);
182  }
183 
184 
186  TextFile::~TextFile() {
187  Close();
188  }
189 
190 
191  // Methods
192 
217  void TextFile::Open(const QString &filename, const char *openmode,
218  const char *extension) {
219  // Open (filename [,openmode] [, with_extension ])
220  // default openmode = 'input'
221  // default extension = 'txt'; extension = "" opens without default
222 
223  // note: in append mode, the input and output pointers move together
224 
225 
226  // Don't open if it already is
227  if(p_stream.is_open()) {
228  QString message = "TextFile:Open:-> Already opened with this object: ["
229  + QString(openmode) + "]:[" + p_filename + "]";
230  throw IException(IException::Programmer, message, _FILEINFO_);
231  }
232 
233  p_openmode = 0;
234 
235  // Save the filename for error messages
236 
237  Isis::FileName filenameTmp(filename);
238  filenameTmp.addExtension(extension);
239  p_filename = filenameTmp.expanded();
240 
241 
242  // input, output, overwrite, append
243 
244  string chkOpenmode = Isis::IString(openmode).DownCase();
245  if(chkOpenmode == "input") {
246  p_openmode = 1;
247  }
248  else if(chkOpenmode == "output") {
249  p_openmode = 2;
250  }
251  else if(chkOpenmode == "overwrite") {
252  p_openmode = 3;
253  }
254  else if(chkOpenmode == "append") {
255  p_openmode = 4;
256  }
257  else {
258  QString message = "TextFile::-> Unknown openmode: (input, output, overwrite, append):["
259  + QString(openmode) + "]:[" + p_filename + "]";
260  throw IException(IException::Programmer, message, _FILEINFO_);
261  }
262 
263  // Input
264  if(p_openmode == 1) {
265  p_stream.open(p_filename.toLatin1().data(), fstream::in);
266  }
267  // Output
268  else if(p_openmode == 2) {
269  // first check if file already exists
270  if(filenameTmp.fileExists() && QFileInfo(filenameTmp.toString()).size() > 0) {
271  QString message = "TextFile:Open: -> Output file already exists ["
272  + QString(openmode) + "]:[" + p_filename + "]";
273  throw IException(IException::Io, message, _FILEINFO_);
274  }
275 
276  p_stream.open(p_filename.toLatin1().data(), fstream::in | fstream::out | fstream::trunc);
277  p_stream.clear();
278  }
279  // Overwrite
280  else if(p_openmode == 3) {
281  p_stream.open(p_filename.toLatin1().data(), fstream::in | fstream::out | fstream::trunc);
282  }
283  // Append
284  else if(p_openmode == 4) {
285  // Open in append if it does exist, otherwise, open in overwrite mode
286  if(filenameTmp.fileExists()) {
287  p_stream.open(p_filename.toLatin1().data(), fstream::in | fstream::out | fstream::ate);
288  }
289  else {
290  p_stream.open(p_filename.toLatin1().data(), fstream::in | fstream::out | fstream::trunc);
291  }
292  }
293 
294  if(!p_stream.is_open()) {
295  QString message = "TextFile:Open:-> Unable to open: ["
296  + QString(openmode) + "]:[" + p_filename + "]";
297  throw IException(IException::Io, message, _FILEINFO_);
298  }
299  }
300 
301  bool TextFile::OpenChk(bool bailIfNotOpen) {
302  if(p_stream.is_open()) {
303  return(true);
304  }
305  else {
306  if(bailIfNotOpen) {
307  QString message = "TextFile::-> File not open: [" + p_filename + "]";
308  throw IException(IException::Programmer, message, _FILEINFO_);
309  }
310  else {
311  return(false);
312  }
313  }
314  }
315 
317  void TextFile::Rewind() {
318  OpenChk(true);
319  if(p_stream.eof()) {
320  p_stream.clear();
321  }
322  p_stream.seekg(0, ios_base::beg);
323  }
324 
326  void TextFile::Close() {
327  if(p_stream.is_open()) {
328  p_stream.flush();
329  p_stream.close();
330  }
331  }
332 
333  // vector array
334  void TextFile::GetFile(std::vector<QString> &lines, const int &maxLinesToRead,
335  const bool skipComments) {
336  OpenChk(true);
337  QString line;
338  int lineCount = 0;
339  while(GetLine(line, skipComments)) {
340  if(maxLinesToRead > 0) {
341  if(lineCount++ >= maxLinesToRead) {
342  break;
343  };
344  }
345  lines.push_back(line);
346  }
347  }
348 
349  // string array
350  void TextFile::GetFile(QString *lines, const int &maxLinesToRead,
351  const bool skipComments) {
352  OpenChk(true);
353  QString line;
354  int lineCount = 0;
355  while(GetLine(line, skipComments)) {
356  if(maxLinesToRead > 0) {
357  if(lineCount > maxLinesToRead) {
358  break;
359  };
360  }
361  else if(lines[lineCount] == "\0") {
362  break;
363  }
364  lines[lineCount] = line;
365  lineCount++;
366  }
367  }
368 
369  // vector array
370  void TextFile::PutFile(std::vector<QString> &lines, const int &maxLinesToWrite) {
371  OpenChk(true);
372  for(int lineCount = 0; lineCount < (int) lines.size(); lineCount++) {
373  if(maxLinesToWrite > 0) {
374  if(lineCount > maxLinesToWrite) {
375  break;
376  };
377  }
378  PutLine(lines[lineCount]);
379  }
380  }
381 
382  // string array
383  void TextFile::PutFile(const QString *lines, const int &maxLinesToWrite) {
384  OpenChk(true);
385  int lineCount = 0;
386  while(true) {
387  if(maxLinesToWrite > 0) {
388  if(lineCount > maxLinesToWrite) {
389  break;
390  };
391  }
392  else if(lines[lineCount] == "\0") {
393  break;
394  }
395  PutLine(lines[lineCount]);
396  lineCount++;
397  }
398  }
399 
411  bool TextFile::GetLine(QString &line, bool skipComments) {
412  return (p_GetLine(line, skipComments));
413  }
414 
424  bool TextFile::GetLine(bool skipComments) {
425  QString line;
426  return (p_GetLine(line, skipComments));
427  }
428 
437  bool TextFile::GetLineNoFilter(QString &line) {
438  return (p_GetLine(line, false));
439  }
440 
447  bool TextFile::GetLineNoFilter() {
448  QString line;
449  return (p_GetLine(line, false));
450  }
451 
463  bool TextFile::p_GetLine(QString &line, bool chkComment) {
464  OpenChk(true);
465 
466  line = "";
467 
468  // Try to read the next line
469  std::string lineStdString;
470  getline(p_stream, lineStdString);
471  line = lineStdString.c_str();
472 
473  // Check for end of file
474  if(p_stream.eof()) {
475  return false;
476  }
477 
478  // See if an error occured
479  if(!p_stream.good()) {
480  line = "";
481  QString message = "TextFile:GetLine: -> Error reading text file: ["
482  + p_filename + "]";
483  throw IException(IException::Io, message, _FILEINFO_);
484  }
485 
486  // See if we have a comment and if we need to ignore
487  if(chkComment) {
488  if(p_commentString.length()) {
489  int locComment = line.indexOf(p_commentString);
490  if(locComment != -1) {
491  int afterWhiteSpace = line.indexOf(QRegExp("[^\\s]"));
492  if((locComment == 0) || (locComment == afterWhiteSpace)) {
493  return p_GetLine(line, chkComment);
494  }
495  }
496  }
497  }
498 
499  // We have a good line
500  return true;
501  }
502 
508  void TextFile::PutLine(const QString &line) {
509  PutLine(line.toLatin1().data());
510  }
511 
522  void TextFile::PutLine(const char *line) {
523  OpenChk(true);
524 
525  // Try to write the next line
526  p_stream << line << p_newLineString;
527  // See if an error occured
528  if(!p_stream.good()) {
529  if(p_openmode != 1) {
530  QString message = "TextFile:PutLine: -> Error writing text file: ["
531  + p_filename + "]";
532  throw IException(IException::Io, message, _FILEINFO_);
533  }
534  else {
535  QString message =
536  "TextFile:PutLine: -> Attempt to write to INPUT - Read Only text file: ["
537  + p_filename + "]";
538  throw IException(IException::Programmer, message, _FILEINFO_);
539  }
540  }
541  }
542 
549  void TextFile::PutLineComment(const QString &line) {
550  PutLine(p_commentString + line);
551  }
552 
559  void TextFile::PutLineComment(const char *line) {
560  PutLine(p_commentString + QString(line));
561  }
562 
563 
564  QString TextFile::GetComment() {
565  return(p_commentString);
566  }
567 
568 
577  void TextFile::SetComment(const char *commentString) {
578  p_commentString = commentString;
579  }
580 
581 
582  QString TextFile::GetNewLine() {
583  return(p_newLineString);
584  }
585 
593  void TextFile::SetNewLine(const char *newLineString) {
594  p_newLineString = newLineString;
595  }
596 
607  int TextFile::LineCount(const int &maxLinesToRead) {
608  OpenChk(true);
609 
610  // LineCount ( [maxLinesToRead] ) --- returns number of lines in open file
611 
612  bool eofStat = false;
613  if(p_stream.eof()) { // current state of stream is 'eof'
614  eofStat = true;
615  p_stream.clear();
616  }
617 
618  streampos savePos = p_stream.tellg();
619  p_stream.seekg(0, ios_base::beg);
620 
621  int lineCount = 0;
622  string tmpLine;
623  if(maxLinesToRead > 0) {
624  while((getline(p_stream, tmpLine)) && (lineCount <= maxLinesToRead)) {
625  lineCount++;
626  }
627  }
628  else {
629  while(getline(p_stream, tmpLine)) {
630  lineCount++;
631  }
632  }
633 
634  if(p_stream.eof()) {
635  p_stream.clear();
636  }
637 
638  p_stream.seekg(savePos, ios_base::beg);
639 
640  if(eofStat) { // restore current state of stream 'eof'
641  p_stream.seekg(0, ios_base::end);
642  p_stream.get();
643  }
644  return lineCount;
645  }
646 
652  streamsize TextFile::Size() {
653  OpenChk(true);
654 
655  // Size () --- returns file size in bytes
656 
657  bool eofStat = false;
658  if(p_stream.eof()) { // current state of stream is 'eof'
659  eofStat = true;
660  p_stream.clear();
661  }
662 
663  streampos savePos = p_stream.tellg();
664  p_stream.seekg(0, ios_base::end);
665  streamsize bytes = p_stream.tellg();
666  p_stream.seekg(savePos, ios_base::beg);
667 
668  if(eofStat) { // restore current state of stream 'eof'
669  p_stream.seekg(0, ios_base::end);
670  p_stream.get();
671  }
672  return bytes;
673  }
674 } // end namespace isis
675 
676 
Isis::IString::DownCase
IString DownCase()
Converts all upper case letters in the object IString into lower case characters.
Definition: IString.cpp:644
Isis::FileName
File name manipulation and expansion.
Definition: FileName.h:100
Isis::FileName::fileExists
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition: FileName.cpp:449
Isis::TextFile
Provides access to sequential ASCII stream I/O.
Definition: TextFile.h:38
Isis::FileName::expanded
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:196
Isis::FileName::addExtension
FileName addExtension(const QString &extension) const
Adds a new extension to the file name.
Definition: FileName.cpp:225
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::FileName::toString
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
Definition: FileName.cpp:515
std
Namespace for the standard library.
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16