0

After an outfile data is processed, I want to take in that data back in again using an fstream variable called infile. Can an operation like the one below be possible after the outfile is complete? My main goal is to read back in what was randomly put out to the file so I can process it into a linked list eventually. I have tested a code similar to this but I get zeroes as a result. Thanks.

   ifstream infile;
   string FileName = "Numbers.txt";
   infile.open(FileName);
   while (infile)
   {
        infile >> RandomNumber;
        cout << RandomNumber << endl;
   }
   infile.close();
  • Why would you think this may not be possible? – Sam Varshavchik Mar 25 '16 at 02:15
  • because I tested a code almost similar to this.. and when I did.. I got zeroes – Nathan Drieling Mar 25 '16 at 02:16
  • 1
    Check the file to see if there are any `0`s. If so, it's not the input code that is screwing up, it's the output code. Also, make sure you are setting `rand` up right, with `srand()`. – Greg M Mar 25 '16 at 02:25
  • `while (infile)` this will always be true change it to `if`. And use `while(infile >> RandomNumber)` to read everything from the file – DimChtz Mar 25 '16 at 02:29
  • @DimChtz The if is unnecessary due to the fact that `operator>>(istream&, int&)` returns the stream that's passed in. so `while (infile >> RandomNumber)` evaluates to `while(infile)` with the only difference being that the `operator>>` has the chance to set the good bit to false and `while (infile)` evaluates to `while (operator bool(istream&))` which is just a check to make sure the failbit and badbit aren't set. http://www.cplusplus.com/reference/ios/ios/operator_bool/ http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ – user2913685 Mar 25 '16 at 03:06

3 Answers3

1

This should work if ( infile ) will check if the file is opened and while ( infile >> RandomNumber ) will get all the numbers in the file:

ifstream infile;
string FileName = "Numbers.txt";
infile.open(FileName);
if ( infile ) {
    while ( infile >> RandomNumber ) {
         cout << RandomNumber << endl;
    }
}
infile.close();
DimChtz
  • 4,043
  • 2
  • 21
  • 39
  • And from that point, you can basically put that data anywhere like a linked list, array, etc? – Nathan Drieling Mar 25 '16 at 02:49
  • Yes, you can put the data anywhere you want. – DimChtz Mar 25 '16 at 02:50
  • The if statement is unnecessary. The while is already going to perform that if. See my comment to the main question. – user2913685 Mar 25 '16 at 03:09
  • 1
    @user2913685: true for things as is, but mildly production-quality code would add an `else` and report failure to open the file; I typically write a la `if (std::ifstream in(filename)) while (in >> x) use(x); else throw std::runtime_error("couldn't open " + filename);`. (For even more robust code, you want to differentiate EOF from parsing failure.) – Tony Delroy Mar 25 '16 at 05:48
  • @Tony yes but I prefer the notation `if ( !infile.is_open() ) { // Throw Error, Log or Print Message or return; }` then do work. I prefer this because when you get into the habit of checking for error cases first, then once you know that data is in a valid state it is safe to do the work; this also allows you to develop a cleaner program. Easier to debug and saves time. – Francis Cugler Mar 25 '16 at 06:55
  • 1
    @FrancisCugler: there's one in every crowd ;-). Cheers. – Tony Delroy Mar 25 '16 at 06:57
  • @Tony I agree, and I'm not saying your method is wrong for it is just as valid. That is why it is called a preference and not a standard. However from a developmental viewpoint it helps to minimize error prone code. – Francis Cugler Mar 25 '16 at 06:59
  • 1
    @FrancisCugler: for sure; more seriously (than my last post), there's often value in consistently having the successful handling first in if/else structures - if concentrates the information about what code's *trying* to do towards the top of the code, but there's also value in quickly handling errors and simplifying the cumulative state affecting the rest of a function; which is better on balance depends on the specific libraries used, number of branches possible, consistency of RAII use, frequency of necessary "prologue" code pre function exit etc.. – Tony Delroy Mar 25 '16 at 07:04
  • Typical parsing: `std::string filename("filename.ext"); std::ifstream in; in.open( filename.c_str(), std::ios_base::in ); if ( !in.is_open() ) { throw Error; } while ( !in.eof() ) { // Parse File; Save Contents To Structures, Classes, Containers, etc.; }` – Francis Cugler Mar 25 '16 at 07:06
  • @FrancisCugler: separate subject, but your `while ( !in.eof() )` is a common mistake in iostream usage... see e.g. [here](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – Tony Delroy Mar 25 '16 at 07:07
  • @Tony yes that is true, but for in a comment section it is too large for me to post my filehandler class, and parser setup, but basically I'll have a class that parses data from a file and in its constructor I would have `while ( getNextLine() ) { parseThis(); }` and the `getNextLine()` returns true or false. This class will have a fileHandler member and within the `getNextLine()` I would have this: `if ( !m_file.readLine( m_strLine ) ) { return false; } ++m_uLineNumber; // Some Other Work; return true;` and as for my `readLine()` ... – Francis Cugler Mar 25 '16 at 07:37
  • @Tony (...continued) I have: `if ( m_fstream.eof() ) { return false; } std::getline( m_fstream, strLine ); return true;` where the strLine is passed to this function. Now my classes that have these filehandles are not direct `std::ifsream` or `std::ofstream` objects. I have a FileHandler class that is a base class, and from there I have derived readers and writers for both text, textures, and custom data (binary) files. – Francis Cugler Mar 25 '16 at 07:39
  • Still `if ( m_fstream.eof() ) { return false; } std::getline( m_fstream, strLine );` is a dangerous idea for anything `istream`-based: you get an extra call where it returns `true` with `strLine` empty at the end of the file; for example, if the complete file content is `"one line input\n"`, you'll parse that as two strings: `"one line input"`, `""`. If you've hacked it up so your classes don't do that, they'll fail in other uses where people expect real streams. – Tony Delroy Mar 25 '16 at 07:43
  • @Tony True; but I have a Utility class that has all static functions for string manipulation. and within that class is a function to trim all leading and ending white spaces including newlines and carriage returns. And this function is used within my parsers after I retrieve the line of text from the file. In fact it is in my `getNextLine()` after I increment the line counter I have a call to `m_strLine = Utility::trim( m_strLine );` to remove the white spaces. – Francis Cugler Mar 25 '16 at 07:47
  • @Tony yes it may be misleading at first from my initial comment but the general idea is to do a loop while you are not at the end of a file and once you reach the end of the file break out of the loop. – Francis Cugler Mar 25 '16 at 07:52
  • @FrancisCugler: "to loop while you are not at the end of a file" is almost the right thing to do, but you need to actively skip whitespace before checking, and then you can't assume input will succeed (as in your answer's `in >> RandomNumber;`), as you might hit unparsable non-whitespace content, so all up: `while (in >> std::skipws && !in.eof()) if (in >> RandomNumber) ...use it... else ...report bad/fail...;` is robust, but too rare: in quickly hacked up C++ programs, people often treat eof and bad input the same.... – Tony Delroy Mar 25 '16 at 08:40
  • @Tony I understand what you are saying, it is too large for me to post my library, but what I can do is show you a class hierarchy of my fileHandlers in an answer below. – Francis Cugler Mar 25 '16 at 18:56
1

This is not an answer to the OPs question but rather it is provided towards a small conversation within a series of comments about reading files and parsing data. This is directed towards Tony and any who would wish to use this class setup. There are some things with in this class that pertain to other classes within my library, some of these include my Logger which would log messages to either a file or the console, and the message types are either Info, Warning, Error or Console. My Logger is derived from a Singleton class since I would only need one logger per solution to handle all messages. I have a Utility Class that hands a majority of string manipulation functions where the constructor is private and all functions or members are declared as static. This class also relies on an ExceptionHandler class that will accept either std::strings or std::ostringstream objects. My Logger accepts the same. Also some of my classes also rely on a BlockThread class that allows to work with multithreading which upon construction it will Create and Initialize a CriticalSection then Enter the Critical Section and then upon Destruction it will Leave and then Destroy the CriticalSection. Now as for this demonstration I will only be showing my FileHandler Classes along with 2 of its derived types, TextFileReader and TextFileWriter. I have more derived FileHandlers that work with reading in texture files, custom data structures etc, that work on binary files as opposed to text file, but for the purpose of this only the Text File Handlers will be shown.

FileHandler.h

#ifndef FILE_HANDLER_H
#define FILE_HANDLER_H

namespace util {

//class AssetStorage;

class FileHandler {
protected:
    //static AssetStorage* m_pAssetStorage;

    std::fstream    m_fileStream;
    std::string     m_strFilePath;
    std::string     m_strFilenameWithPath;

private:
    bool m_bSaveExceptionInLog;

public:
    virtual ~FileHandler();

protected:
    FileHandler( const std::string& strFilename, bool bSaveExceptionInLog );
    void throwError( const std::string& strMessage ) const;
    void throwError( const std::ostringstream& strStreamMessage ) const;

    bool getString( std::string& str, bool appendPath );

private:
    FileHandler( const FileHandler& c ); // Not Implemented
    FileHandler& operator=( const FileHandler& c ); // Not Implemented

}; // FileHandler

} // namespace util

FileHandler.cpp

#include "stdafx.h"
#include "FileHandler.h"

namespace util {

// ----------------------------------------------------------------------------
// FileHandler()
FileHandler::FileHandler( const std::string& strFilename, bool bSaveExceptionInLog ) :
m_bSaveExceptionInLog( bSaveExceptionInLog ),
m_strFilenameWithPath( strFilename ) {

    // Extract Path Info If It Exists
    std::string::size_type lastIndex = strFilename.find_last_of( "/\\" );
    if ( lastIndex != std::string::npos ) {
        m_strFilePath = strFilename.substr( 0, lastIndex );
    }

    if ( strFilename.empty() ) {
        throw ExceptionHandler( __FUNCTION__ + std::string( " missing filename", m_bSaveExceptionInLog ) );
    }
} // FileHandler

// ----------------------------------------------------------------------------
// ~FileHandler
FileHandler::~FileHandler() {
    if ( m_fileStream.is_open() ) {
        m_fileStream.close();
    }
} // ~FileHandler

// ----------------------------------------------------------------------------
// throwError()
void FileHandler::throwError( const std::string& strMessage ) const {
    throw ExceptionHandler( "File [" + m_strFilenameWithPath + "] " + strMessage, m_bSaveExceptionInLog );
} // throwError( const std::string )

// ----------------------------------------------------------------------------
// throwError()
void FileHandler::throwError( const std::ostringstream& strStreamMessage ) const {
    throwError( strStreamMessage.str() );
} // throwError( const std::ostringstream )

// ----------------------------------------------------------------------------
// getString()
bool FileHandler::getString( std::string& str, bool appendPath ) {
    m_fileStream.read( &str[0], str.size() );
    if ( m_fileStream.fail() ) {
        return false;
    }

    // Trim Right
    str.erase( str.find_first_of( char(0) ) );

    if ( appendPath && !m_strFilePath.empty() ) {
        // Add Path If One Exixsts
        str = m_strFilePath + "/" + str;
    }

    return true;
} // getString

} // namespace util

TextFileReader.h

#ifndef TEXT_FILE_READER_H
#define TEXT_FILE_READER_H

#include "FileHandler.h"

namespace util {

class TextFileReader : public FileHandler {
private:

public:
    explicit TextFileReader( const std::string& strFilename );
    // virtual ~TextFileReader(); // Default OK

    std::string readAll() const;
    bool        readLine( std::string& strLine );

private:
    TextFileReader( const TextFileReader& c ); // Not Implemented
    TextFileReader& operator=( const TextFileReader& c ); // Not Implemented
}; // TextFileReader

} // namespace util

#endif // TEXT_FILE_READER_H

TextFileReader.cpp

#include "stdafx.h"
#include "TextFileReader.h"

namespace util {

// ----------------------------------------------------------------------------
// TextFileReader()
TextFileReader::TextFileReader( const std::string& strFilename ) :
FileHandler( strFilename, true ) {
    m_fileStream.open( m_strFilenameWithPath.c_str(), std::ios_base::in );
    if ( !m_fileStream.is_open() ) {
        throwError( __FUNCTION__ + std::string( " can not open file for reading" ) );
    }
} // TextFileReader

// ----------------------------------------------------------------------------
// readAll()
std::string TextFileReader::readAll() const {
    std::ostringstream strStream;
    strStream << m_fileStream.rdbuf();

    return strStream.str();
} // readAll

// ----------------------------------------------------------------------------
// readLine()
// Returns A String Containing The Next Line Of Text Stored In The File
bool TextFileReader::readLine( std::string& strLine ) {
    if ( m_fileStream.eof() ) {
        return false;
    }
    std::getline( m_fileStream, strLine );
    return true;
} // readLine

} // namespace util

TextFileWriter.h

#ifndef TEXT_FILE_WRITER_H
#define TEXT_FILE_WRITER_H

#include "FileHandler.h"

namespace util {

class TextFileWriter : public FileHandler {
private:

public:
    TextFileWriter( const std::string& strFilename, bool bAppendToFile, bool bSaveExceptionInLog = true );
    // virtual ~TextFileWriter(); // Default OK

    void write( const std::string& str );

private:
    TextFileWriter( const TextFileWriter& c ); // Not Implemented
    TextFileWriter& operator=( const TextFileWriter& c ); // Not Implemented

}; // TextFileWriter

} // namespace util

#endif // TextFileWriter

TextFileWriter.cpp

#include "stdafx.h"
#include "TextFileWriter.h"

namespace util {

// ----------------------------------------------------------------------------
// TextFileWriter()
TextFileWriter::TextFileWriter( const std::string& strFilename, bool bAppendToFile, bool bSaveExceptionInLog ) :
FileHandler( strFilename, bSaveExceptionInLog ) {
    m_fileStream.open( m_strFilenameWithPath.c_str(),
      std::ios_base::out | (bAppendToFile ? std::ios_base::app : std::ios_base::trunc) );

    if ( !m_fileStream.is_open() ) {
        throwError( __FUNCTION__ + std::string( " can not open file for writing" ) );
    }
} // TextFileWriter

// ----------------------------------------------------------------------------
// write()
void TextFileWriter::write( const std::string& str ) {
    m_fileStream << str;
} // write

} // namespace util

And Here is some code fragments of a class that used the FileHandlers.

Here is the class header that uses the FileHandler It reads in a text file and parses it to determine which GUI objects to create, load into memory and how they are to be displayed on the screen, it will also nest one GUI type as a child to another. I will not be showing the full implementation of this class but only a few functions where it concerns the use of using the FileHandlers.

GuiLoader.h

#ifndef GUI_LOADER_H
#define GUI_LOADER_H

#include "Engine.h"

#include "CommonStructs.h"
#include "Property.h"
#include "TextFileReader.h"

namespace vmk {

class AssetStorage;

class GuiCompositeElement;
class GuiElement;
class GuiLayout;
class GuiRenderable;
class GuiText;

class VisualMko;

class GuiLoader sealed {
    friend GuiElement* Engine::loadGui( const std::string& strFilename ) const;
private:
    std::string     m_strFilename;
    util::TextFileReader  m_file;

    bool        m_inBlockComment;
    unsigned    m_uNumBracesOpened;
    unsigned    m_uLineNumber; // Keep Track OfLine Number For Error Messages

    GuiElement* m_pLastGuiRoot;
    std::vector<GuiCompositeElement*> m_vpParents;

    std::string m_strLine;

    std::unordered_map<std::string, TextureInfo> m_mTextureInfos;
    std::unordered_map<std::string, FontFace>    m_mFontFace;   

    FontManager*  m_pFontManager;
    AssetStorage* m_pAssetStorage;

public:
    // virtual ~GuiLoader(); // Default Ok

    GuiElement* getRoot() const;

private:
    GuiLoader( const std::string& strFilename );

    GuiLoader( const GuiLoader& c ); // Not Implemented
    GuiLoader& operator=( const GuiLoader& c ); // Not Implemented

    bool    getNextLine();
    std::string getFailedLocation() const;
    void    removeComments();
    void    parseGui();
    bool    handleOpenBrace( unsigned uStartLocation, GuiCompositeElement* pGui );
    void    addToParent( GuiRenderable* pRenderable ) const;

    bool    getParameter( std::string strParam, unsigned uStartLocation, std::string& strValue, bool isRequired = true, char endCharacter = ' ' ) const;
    void    setOptionalParameters( unsigned uStartLocation, GuiElement* pGui ) const;
    void    getOptionalLayoutParameters( unsigned uStartLocation, glm::ivec2& offsetFromParent, Gui::Alignment& eAlignChildren, glm::uvec2& size, std::string& strId ) const;
    void    setLayoutParameters( unsigned uStartLocation, GuiLayout* pLayout ) const;
    bool    getOptionalBackgroundParameters( unsigned uStartLocation, TextureInfo& textureInfo, glm::uvec2& origin ) const;
    bool    getOptionalBackgroundParameters( unsigned uStartLocation, TextureInfo& textureInfo, glm::uvec2& origin, glm::uvec2& size, bool isRequired = true ) const;
    void    getRequiredTextParameters( unsigned uStartLocation, FontFace& fontFace, std::string& strText ) const;

    void    setTextShadowParameters( unsigned uStartLocation, GuiText* pGui ) const;

    void    setVisualMkoParameters( unsigned uStartLocation, VisualMko* pVisualMko ) const;

}; // GuiLoader

} // namespace vmk

#endif // GUI_LOADER_H

GuiLoader.cpp - Only A Few Portions Are Shown

#include "stdafx.h"
#include "GuiLoader.h"

#include "AssetStorage.h"
#include "FontManager.h"
#include "Gui.h"
#include "Image2d.h"
#include "Logger.h"
#include "TextureFileReader.h"
#include "Utility.h"

using namespace util;

namespace vmk {

// ----------------------------------------------------------------------------
// GuiLoader()
GuiLoader::GuiLoader( const std::string& strFilename ) :
m_strFilename( strFilename ),
m_file( strFilename ),
m_inBlockComment( false ),
m_uNumBracesOpened( 0 ),
m_uLineNumber( 0 ),
m_pLastGuiRoot( nullptr ),
m_pFontManager( FontManager::get() ),
m_pAssetStorage( AssetStorage::get() ) {
    while ( getNextLine() ) {
        parseGui();
    }

    if ( m_uNumBracesOpened > 0 ) {
        std::ostringstream strStream;
        strStream << __FUNCTION__ <<  getFailedLocation() << ". Missing " << m_uNumBracesOpened << " closing brace" << ( m_uNumBracesOpened > 1 ? "s" : "" ) << ".";
        throw ExceptionHandler( strStream );
    }

    if ( m_inBlockComment ) {
        std::ostringstream strStream;
        strStream << __FUNCTION__ << getFailedLocation() << ". Missing closing block comment */.";
    }
} // GuiLoader

// ----------------------------------------------------------------------------
// getRoot()
GuiElement* GuiLoader::getRoot() const {
    return m_pLastGuiRoot;
} // getRoot

// ----------------------------------------------------------------------------
// getNextLine()
// Returns True If Got A Line Of Text (Could Be Blank If It Is All Commented
// Out Or If It Truly Was A Blank Line). False is Returned When There Is
// No More Data In The File
bool GuiLoader::getNextLine() {
    if ( !m_file.readLine( m_strLine ) ) {
        return false;
    }

    ++m_uLineNumber;

    m_strLine = Utility::trim( m_strLine );
    //std::cout << m_uLineNumber << ": " << m_strLine << std::endl; // Use This For Debugging The GuiLoader

    removeComments();

    return true;
} // getNextLine

// ... Other Functions Here

} // namespace vmk

This was presented to show the robustness of my file handling classes. There are many other classes not shown here. My library is a part of a 3D Graphics Rendering Library that uses Modern OpenGL. There are several hundred class objects and 100,000s of lines of code for doing 3D graphics rendering, sprite loading, physics simulation, animation, audio playback, audio stream playback, and much more. Not all of this source code is of my own design for this code is copy right protected by Marek A. Krzeminski, MASc and his works can be found at www.MarekKnows.com

All code shown here was not copied and pasted from his site, it was all hand typed while following along with his video tutorials. It was compiled and debug manually. This project has been in the works for a couple of years, and still to this day more is being added. I have been a proud member of his website and community since 2007-2008.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • Hi Francis. That's a lot of code! It doesn't show a great understanding of the C++ Standard Library features being wrapped, e.g. - `FilterHandler`'s destructor never needs to call `m_fileStream.close();`, as the stream destructor handles that internally. `TextFileReader::readLine` has the exact bug I described to you with EOF handling, and `'::readAll` involves a string copy of the entire file content that won't be optimised away. – Tony Delroy Mar 27 '16 at 08:59
0
int number = 0;
string filename( "Numbers.txt" );
std::ofstream out;
std::ifstream in;

std::cout << "enter a number: << std::endl;
std::cin >> number;   

out.open( filename.c_str(), std::ios_base::out );
if ( !out.is_open() ){
  // Print, Log Error, Throw Error, Return Etc.
}  

for ( int i = 0; i < number; i++ ) {
     out << rand() % 100 << std::endl;
}
out.close();

in.open( filename.c_str(), std::ios_base::in );
if ( !in.is_open() ) {
    // Error Case Here
}

while ( !in.eof() ) { // Usually bad practice; but my file handling classes are parser objects are too large to show here.
    in >> RandomNumber;
    std::cout << RandomNumber << endl;
}
infile.close();
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59