c++ 可以使用 fstream infile 从最近使用的 ofstream outfile 中收集数据吗?

c++ can an fstream infile be used to gather data from an recently used ofstream outfile?

处理完 outfile 数据后,我想使用名为 infile 的 fstream 变量再次将该数据取回。 outfile完成后是否可以进行如下操作?我的主要目标是读回随机放入文件的内容,以便最终将其处理成链表。我已经测试了与此类似的代码,但结果是零。谢谢

   ifstream infile;
   string FileName = "Numbers.txt";
   infile.open(FileName);
   while (infile)
   {
        infile >> RandomNumber;
        cout << RandomNumber << endl;
   }
   infile.close();

这应该有效 if ( infile ) 将检查文件是否已打开,while ( infile >> RandomNumber ) 将获取文件中的所有数字:

ifstream infile;
string FileName = "Numbers.txt";
infile.open(FileName);
if ( infile ) {
    while ( infile >> RandomNumber ) {
         cout << RandomNumber << endl;
    }
}
infile.close();
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();

这不是对 OP 问题的回答,而是针对一系列关于读取文件和解析数据的评论中的小型对话提供的。这是针对 Tony 和任何希望使用此 class 设置的人。这个 class 中有一些东西与我的库中的其他 classes 相关,其中一些包括我的 Logger,它将消息记录到文件或控制台,消息类型是信息、警告、错误或控制台。我的 Logger 派生自 Singleton class,因为每个解决方案我只需要一个记录器来处理所有消息。我有一个 Utility Class 处理大多数字符串操作函数,其中构造函数是私有的,所有函数或成员都声明为静态的。这个 class 还依赖于一个 ExceptionHandler class,它将接受 std::strings 或 std::ostringstream objects。我的记录器接受相同的。此外,我的一些 classes 还依赖于允许使用多线程的 BlockThread class,在构建时它将创建并初始化一个 CriticalSection,然后进入关键部分,然后在销毁时它将离开,然后销毁 CriticalSection。现在对于这个演示,我将只展示我的 FileHandler Classes 及其两个派生类型,TextFileReader 和 TextFileWriter。我有更多派生的 FileHandlers,可用于读取纹理文件、自定义数据结构等,可用于二进制文件而不是文本文件,但出于此目的,将仅显示文本文件处理程序。

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

这是使用 FileHandlers 的 class 的一些代码片段。

这是使用 FileHandler 的 class header 它读取文本文件并解析它以确定要创建哪个 GUI objects,加载到内存中以及它们如何要显示在屏幕上,它还会将一种 GUI 类型作为 child 嵌套到另一种 GUI 类型。我不会展示此 class 的完整实现,而只会展示一些与使用 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 - 只显示了一小部分

#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

这是为了展示我的文件处理 classes 的稳健性。还有许多其他 classes 未在此处显示。我的库是使用现代 OpenGL 的 3D 图形渲染库的一部分。有数百 class objects 和 100,000 行代码用于进行 3D 图形渲染、精灵加载、物理模拟、动画、音频播放、音频流播放等等。并非所有源代码都是我自己设计的,因为此代码的版权受 Marek A. Krzeminski、MASc 和他的作品的版权保护,可以在 www.MarekKnows.com

找到

这里显示的所有代码都不是从他的站点复制和粘贴的,都是在跟随他的视频教程时手工输入的。它是手动编译和调试的。这个项目已经进行了几年,直到今天还在增加更多。自 2007 年至 2008 年以来,我一直是他的网站和社区的骄傲成员。