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
18using namespace std;
19namespace Isis {
20
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
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
318 OpenChk(true);
319 if(p_stream.eof()) {
320 p_stream.clear();
321 }
322 p_stream.seekg(0, ios_base::beg);
323 }
324
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
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
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
Adds specific functionality to C++ strings.
Definition IString.h:165
IString DownCase()
Converts all upper case letters in the object IString into lower case characters.
Definition IString.cpp:644
bool GetLine(QString &line, const bool skipComments=true)
Gets next line from file.
Definition TextFile.cpp:411
TextFile()
Constructs an empty TextFile object.
Definition TextFile.cpp:22
void Open(const QString &filename, const char *openmode="input", const char *extension="")
Opens a text file.
Definition TextFile.cpp:217
QString p_newLineString
'newline' string used by PutLine and PutLineComment
Definition TextFile.h:47
void SetComment(const char *commentString="#")
Sets the 'comment' string.
Definition TextFile.cpp:577
QString p_commentString
'comment' string used by GetLine and PutLineComment
Definition TextFile.h:45
std::fstream p_stream
File stream handle.
Definition TextFile.h:41
int LineCount(const int &maxLinesToRead=0)
Counts number of lines in file.
Definition TextFile.cpp:607
int p_openmode
openmode of file: Input, Output, Overwrite, Append
Definition TextFile.h:42
void PutLine(const QString &line)
Writes string to file and appends a 'newline' string.
Definition TextFile.cpp:508
std::streamsize Size()
Counts number of bytes in file.
Definition TextFile.cpp:652
bool GetLineNoFilter()
Gets next NON-COMMENT line from file.
Definition TextFile.cpp:447
~TextFile()
Closes file (if still open). Destroys the TextFile object.
Definition TextFile.cpp:186
void Close()
Closes file. Called automatically by TextFile destructor.
Definition TextFile.cpp:326
void Rewind()
Sets Read / Write pointer to begining of opened file.
Definition TextFile.cpp:317
QString p_filename
FileName of the opened file.
Definition TextFile.h:44
bool p_GetLine(QString &line, bool chkComment)
Gets next line from file.
Definition TextFile.cpp:463
void PutLineComment(const QString &line)
Writes string to file, prepends a 'comment' string and appends a 'newline' string.
Definition TextFile.cpp:549
void SetNewLine(const char *newLineString="\n")
Sets the 'newline' string.
Definition TextFile.cpp:593
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.