如何在写入文件时忽略行

时间:2015-10-20 16:59:16

标签: c++

如何在c ++中的第n行(例如第5行)写入文件? 这是我的尝试:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream  stream1("1.txt");
    string line ;
    ofstream stream2("2.txt");
    int lineNumber = 0;

    while(getline( stream1, line ) )
    {
        if (lineNumber == 5)
        {
         stream2 << "Input" << endl;
         lineNumber = 0;
        }

    lineNumber++;
    }       

    stream1.close();
    stream2.close();    return 0;
}

在&#34; 1.txt&#34;,我有“#34;学生&#34;在第4行,现在我想忽略上面的4行并输入单词&#34;输入&#34;在第5行(低于#34;学生&#34;)。当我运行上面的代码时,输​​出文件是空白的。有任何建议如何解决这个问题?谢谢。

5 个答案:

答案 0 :(得分:2)

如果我理解正确,您只需要2.txt中的1.txt的副本,只需将您的个人内容替换为特定的行号。

在你看来,这个词是“输入”。

这里是我从原始代码修改的代码 -

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream  stream1("1.txt");
    string line ;
    ofstream stream2("2.txt");
    int lineNumber = 0;
    int line_to_replace = 4; //This will replace 5th line

    while(getline( stream1, line ) ) 
    {   
            if (lineNumber == line_to_replace)
            {   
                    stream2 << "Input" << endl;
            }   
            else
                    stream2 << line << endl;

            lineNumber++;
    }    

    stream1.close();
    stream2.close();    
    return 0;
}

输入文件(1.txt) -

sdlfknas
sdfas
sdf
g
thtr
34t4
bfgndty
45y564
grtg

输出文件(2.txt) -

sdlfknas
sdfas
sdf
g
Input
34t4
bfgndty
45y564
grtg

P.S。为了更好地学习和理解编程,我建议不要使用:

using namespace std;

答案 1 :(得分:1)

当你正在阅读第5行时,lineNumber等于4 b / c,你开始计数为0。 更改if(lineNumber == 5)if(lineNumber == 4)您还遇到一个问题,即您正在设置lineNumber = 0然后立即递增到1,因此在再次输出之前,您只需计算4行。

答案 2 :(得分:1)

我会创建一个这样的函数......

bool isBlank(string line) { 
    if (!line.empty()) {
        for (auto x: line) {
            if (isalnum(x)) {
                return false;
            }
        }
    }
    return true;
}

如果字符串为空或没有字母数字字符,则返回true。

您可以在getline语句后立即调用此函数。

isalnum 功能在<cctype>

中指定

答案 3 :(得分:1)

使用代码后,我设法获得了您想要的输出。这是您的代码的更新版本。

#include <iostream>
#include <fstream>

int main() {
    std::ifstream stream1( "1.txt" );
    std::string line;
    std::ofstream stream2( "2.txt" );
    int lineNumber = 1;

    while ( getLine( stream1, line ) ) {
        if ( lineNumber == 5 ) {
            stream2 << "Input" << std::endl;

        } else {
            stream2 << std::endl;
            lineNumber++;
        }
    }

    stream1.close();
    stream2.close();

    return 0;
}

您必须确保的一件事是,在您的1.txt中,第4行上有单词student,您必须在文件中的此文本后至少有2个空行。一个简单的输入或回车将做!如果不这样做,while( getline() )将超出范围且不会读取下一行,并且代码块将永远不会在if()时输入lineNumber == 5语句,并且不会打印文本"Input"到您的stream2文件流对象。

如果1.txt文件中的最后一行文字是带有文字字符串Student的行,这里会发生的是它会将此行文本添加到line字符串变量中然后代码会将lineNumber增加到等于5。下次进入while循环调用getline()时,它返回false,因为你在EOF,因为文件中没有更多的文本行要读入,这导致while循环到断开执行并超出范围,if( lineNumber == 5 )永远不会被调用,因为它嵌套在while循环的范围内。

答案 4 :(得分:0)

我的第一个回答解决了您的问题并将输出正确地输出到您的文本文件。然而,正如我所提到的,在一行文本中读取while循环并对两个文件流使用相同的计数器并不是很优雅。更准确的方法是简化调试,这样就可以一次读取一行完整的输入文件,并将每行保存到字符串中,同时将字符串存储在向量中。这样,您可以一次解析一行所需的每行文本,并且可以轻松遍历矢量以快速找到您的文本行。您还应该进行检查以确保您的文件存在并且正确打开。

#include <iostream>
#include <fstream>
#include <vector>
#include <string>

int main() {
    std::string strTextFileIn( "1.txt" );
    std::ifstream in;
    std::string strLine;
    std::vector<std::string> vFileContents;

    // Open File Stream
    in.open( strTextFileIn.c_str(), std::ios_base::in );
    // Test To Make Sure It Opened Properly And That It Exists
    if ( !in.is_open() ) {
        std::cout << "Failed to open file, check to make sure file exists." << std::endl;
        return -1;
    } else {
        while ( !in.eof() ) {
            // Get Line Of Text And Save To String
            std::getline( in, strLine );
            // Push String Into Vector
            vFileContents.push_back( strLine );
        }
    }

    // Done With File Close File Stream
    if ( in.is_open() ) {
        in.close();
    }

    // Now That We Have Read In The File Contents And Have Saved Each Line Of Text To A String
    // And Stored It In Our Container (Vector) We Can Traverse Our Vector To Find Which String
    // Matches The Text We Are Looking For Retrive Its Indexed Value And Then Write To Our
    // Output File According To Where You Want The Text To Be Written
    unsigned index = 0;
    const std::string strLookup( "Student" );
    for ( unsigned int i = 0; i < vFileContents.size(); i++ ) {
        if ( vFileContents[i] == strLookup ) {
             // Strings Match We Have Our Indexed Value
            index = i;
        }
    }

    // We Want To Write Our Line Of Text 1 Line Past Our Index Value As You Have Stated.
    std::string strTextFileOut( "2.txt" );
    std::ofstream out;

    // Open Our File For Writting
    out.open( strTextFileOut.c_str(), std::ios_base::out );
    if ( !out.is_open() ) {
        std::cout << "Failed To open file.";
        vFileContents.clear();
        return -1;
    } else {
        for ( unsigned int i = 1; i <= index; i++ ) {
            out << std::endl; // Write Blank Lines
        }
        // The Text Or String You Want To Write To File
        out << "Input" << std::endl;         
    }

    // Done With File Stream
    if ( in.is_open() ) {
        in.close();
    }

    // Clear Out Vector
    vFileContents.clear();

    return 0;
} // main

现在可以通过创建用于处理各种文件流对象类型的类层次结构来简化这一过程,这样您就不必编写此代码来打开,关闭,检查有效性,读取完整文件或在你需要的地方一遍又一遍地排队。这使它模块化。但是,此结构依赖于其他一些类,例如ExceptionHandler类和Logger类。下面是一个小型多文件应用程序。

stdafx.h 注意:并非所有这些包含和定义都将在这里使用,但这来自我的一个更大的项目,我只剥离了那些类需要这里,但保留我的标准标题。我删除的唯一内容是&#34; stdafx.h&#34;是什么必须处理OpenGL,Op​​enAL,Ogg - Vorbis,GLM Libraries&amp;的API

#ifndef STDAFX_H
#define STDAFX_H

#define VC_EXTRALEAN // Exclude Rarely Used Stuff Windows Headers - Windows Only

// Instead of Creating Another File That VS Makes For You "targetver.h"
// I Will Just Append Its Contents Here
#include <SDKDDKVer.h> // Windows Only
#include <Windows.h> // Windows Only
#include <process.h>

#include <tchar.h>
#include <conio.h>

#include <memory>
#include <string>
#include <numeric>
#include <vector>
#include <array>
#include <unordered_map>
#include <queue>

#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>

#include "ExceptionHandler.h"

namespace pro {
enum ReturnCode {
    RETURN_OK = 0,
    RETURN_ERROR = 1,
};

extern const unsigned INVALID_UNSIGNED;
extern const unsigned INVALID_UNSIGNED_SHORT;

} // namespace pro

#endif // STDAFX_H

<强> stdafx.cpp

#include "stdafx.h"

namespace pro {
    const unsigned INVALID_UNSIGNED       = static_cast<const unsigned>( -1 );
    const unsigned INVALID_UNSIGNED_SHORT = static_cast<const unsigned short>( -1 );
} // namespace pro

<强> ExceptionHandler.h

#ifndef EXCEPTION_HANDLER_H
#define EXCEPTION_HANDLER_H

namespace pro {

class ExceptionHandler sealed {
private:
    std::string m_strMessage;

public:
    explicit ExceptionHandler( const std::string& strMessage, bool bSaveInLog = true );
    explicit ExceptionHandler( const std::ostringstream& strStreamMessage, bool bSavedInLog = true );
    // ~ExceptionHandler(); // Default Okay
    // ExeptionHandler( const ExceptionHandler& c ); // Default Copy Constructor Okay & Is Needed

    const std::string& getMessage() const;

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

}; // ExceptionHandler

} // namespace pro

#endif // EXCEPTION_HANDLER_H

<强> ExceptionHandler.cpp

#include "stdafx.h"
#include "ExceptionHandler.h"
#include "Logger.h"

namespace pro {

ExceptionHandler::ExceptionHandler( const std::string& strMessage, bool bSaveInLog ) :
m_strMessage( strMessage ) {
    if ( bSavedInLog ) {
        Logger::log( m_strMessage, Logger::TYPE_ERROR );
    }
}

ExceptionHandler::ExceptionHandler( const std::ostringstream& strStreamMessage, bool bSaveInLog ) : 
m_strMessage( strStreamMessage.str() ) {
    if ( bSaveInLog ) {
        Logger::log( m_strMessage, Logger::TYPE_ERROR );
    }
} 

const std::string& ExceptionHandler::getMessage() const {
    return m_strMessage;
}

} // namespace pro

BlockThread.h - 需要记录器

#ifndef BLOCK_THREAD_H
#define BLOCK_THREAD_H

namespace pro {

class BlockThread sealed {
private:
    CRITICAL_SECTION* m_pCriticalSection;

public:
    explicit BlockThread( CRITICAL_SECTION& criticalSection );
    ~BlockThread();

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

}; // BlockThread

} // namespace pro

#endif // BLOCK_THREAD_H

<强> BlockThread.cpp

#include "stdafx.h"
#include "BlockThread.h"

namespace pro {

BlockThread::BlockThread( CRTICAL_SECTION& criticalSection ) {
    m_pCriticalSection = &criticalSection;
    EnterCriticalSection( m_pCriticalSection );
}       

BlockThread::~BlockThread() {
    LeaveCriticalSection( m_pCriticalSection );
}

} // namespace pro

Logger Singleton ,因为在您的应用程序运行时,您只需要一个实例。

<强> Singleton.h

#ifndef SINGLETON_H
#define SINGLETON_H

namespace pro {

class Singleton {
public:
    enum SingletonType {
        TYPE_LOGGER = 0, // Must Be First!
        // TYPE_SETTINGS,
        // TYPE_ENGINE,
    };

private:
    SingletonType m_eType;
public:
    virtual ~Singleton();

protected:
    explicit Singleton( SingletonType eType );

    void logMemoryAllocation( bool isAllocated ) const;

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

}; // Singleton

} // namespace pro

#endif // SINGLETON_H

<强> Singleton.cpp

#include "stdafx.h"
#include "Logger.h"
#include "Singleton.h"
//#include "Settings.h"

namespace pro {

struct SingletonInfo {
    const std::string strSingletonName;
    bool              isConstructed;

    SingletonInfo( const std::string& strSingletonNameIn ) :
    strSingletonName( strSingletonNameIn ),
    isConstructed( false ) {}
};

// Order Must Match Types Defined In Singleton::SingletonType enum
static std::array<SingletonInfo, 1> s_aSingletons = { SingletonInfo( "Logger" ) }; /*,
                                                      SingletonInfo( "Settings" ) };*/ // Make Sure The Number Of Types Matches The Number In This Array

Singleton::Singleton( SingletonType eType ) :
m_eType( eType ) {
    bool bSaveInLog = s_aSingletons.at( TYPE_LOGGER ).isConstructed;

    try {
        if ( !s_aSingletons.at( eType ).isConstructed ) {
            // Test Initialization Order
            for ( int i = 0; i < eType; ++i ) {
                if ( !s_aSingletons.at( i ).isConstructed ) {
                    throw ExceptionHandler( s_aSingletons.at( i ).strSingletonName + " must be constructed before constructing " + s_aSingletons.at( eType ).strSingletonName, bSaveInLog );
                }
            }
            s_aSingletons.at( eType ).isConstructed = true;

            /*if ( s_aSingletons.at( TYPE_ENGINE ).isConstructed &&
                Setttings::get()->isDebugLogginEnabled( Settings::DEBUG_MEMORY ) ) {
                logMemoryAllocation( true );
            }*/

        } else {
            throw ExceptionHandler( s_aSingletons.at( eType ).strSingletonName + " can only be constructed once.", bSaveInLog );
        }
    } catch ( std::exception& ) {
        // eType Is Out Of Range
        std::ostringstream strStream;
        strStream << __FUNCTION__ << " Invalid Singleton Type Specified: " << eType;
        throw ExceptionHandler( strStream, bSaveInLog );
    }
}

Singleton::~Singleton() {
    /*if ( s_aSingletons.at( TYPE_ENGINE ).isConstructed &&
        Settings::get()->isDebugLoggingEnabled( Settings::DEBUG_MEMORY ) ) {
        logMemoryAllocation( false );
    }*/

    s_aSingletons.at( m_eType ).isConstructed = false;
}

void Singleton::logMemoryAllocation( bool isAllocated ) const {
    if ( isAllocated ) {
        Logger::log( "Created " + s_aSingletons.at( m_eType ).strSingletonName );
    } else {
        Logger::log( "Destroyed " + s_aSingletons.at( m_eType ).strSingletonName );
    }
}

} // namespace pro

<强> Logger.h

#ifndef LOGGER_H
#define LOGGER_H

#include "Singleton.h"

namespace pro {

class Logger sealed : public Singleton {
public:
    // Number Of Items In Enum Type Must Match The Number
    // Of Items And Order Of Items Stored In s_aLogTypes
    enum LoggerType {
        TYPE_INFO = 0,
        TYPE_WARNING,
        TYPE_ERROR,
        TYPE_CONSOLE,
    }; // LoggerType

private:
    std::string m_strLogFilename;
    unsigned    m_uMaxCharacterLength;

    std::array<std::string, 4> m_aLogTypes
    const std::string          m_strUnknownLogType;

    HANDLE m_hConsoleOutput;
    WORD   m_consoleDefualtColor;

public:
    explicit Logger( const std::string& strLogFilename );
    virtual ~Logger();

    static void log( const std::string& strText, LoggerType eLogType = TYPE_INFO );
    static void log( const std::ostringstream& strStreamText, LoggerType eLogType = TYPE_INFO );
    static void log( const char* szText, LoggerType eLogType = TYPE_INFO );

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

}; // Logger        

} // namespace pro

#endif // LOGGER_H

<强> Logger.cpp

#include "stdafx.h"
#include "Logger.h"
#include "BlockThread.h"

#include "TextFileWriter.h"

namespace pro {

static Logger* s_pLogger = nullptr;
static CRITICAL_SECTION = s_criticalSection;

// White Text On Red Background
static const WORD WHITE_ON_RED = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED;

Logger::Logger( const std::string& strLogFilename ) :
Singleton( TYPE_LOGGER ),
m_strLogFilename( strLogFilename ),
m_uMaxCharacterLength( 0 ),
m_strUnknownLogType( "UNKNOWN" ) {
    // Order Must Match Types Defined In Logger::Type enum
    m_aLogTypes[0] = "Info";
    m_aLogTypes[1] = "Warning";
    m_aLogTypes[2] = "Error";
    m_aLogTypes[3] = ""; // Console

    // Find Widest Log Type String
    m_uMaxCharacterLength = m_strUnknownLogType.size();
    for each( const std::string& strLogType in m_aLogTypes ) {
        if ( m_uMaxCharacterLength < strLogType.size() ) {
             m_uMaxCharacterLength = strLogType.size();
        }
    }

    InitializeCriticalSection( &s_criticalSection );
    BlockThread blockThread( s_criticalSection ); // Enter Critical Section

    // Start Log File
    TextFileWriter file( m_strLogFilename, false, false );

    // Prepare Console
    m_hConsoleOutput = GetStdHandle( STD_OUTPUT_HANDLE );

    CONSOLE_SCREEN_BUFFER consoleInfo;
    GetConsoleScreenBufferInfo( m_hConsoleOutput, &consoleInfo );
    m_consoleDefaultColor = consoleInfo.wAttributes;

    s_pLogger = this;

    logMemoryAllocation( true ); 

}

Logger::~Logger() {
    logMemoryAllocation( false );
    s_pLogger = nullptr;
    DeleteCriticalSection( &s_criticalSection );
}

void Logger::log( const std::string& strtext, LoggerType eLogType ) {
    log( strText.c_str(), eLogType );
}

void Logger::log( const std::string& strText, LoggerType eLogType ) {
    log( strText.str().c_str(), eLogType );
}

void Logger::log( const char* szText, LoggerType eLogType ) {
    if ( nullptr == s_pLogger ) {
        std::cout << "Logger has not been initialized, can not log " << szText << std::endl;
        return;
    }

    BlockThread blockThread( s_criticalSection ); // Enter Critical Section

    std::ostringstream strStream;

    // Default White Text On Red Background
    WORD textColor = WHITE_ON_RED;

    // Chose Log Type Text String, Display "UNKNOWN" If eLogType Is Out Of Range
    strStream << std::setfill(' ') << std::setw( s_pLogger->m_uMaxCharacterLength );

    try {
        if ( TYPE_CONSOLE != eLogType ) {
            strStream << s_pLogger->m_aLogTypes.at( eLogType );
        }
        if ( TYPE_WARNING == eLogType ) {
            // Yellow
            textColor = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN;
        } else if ( TYPE_INFO == eLogType ) {
            // Green
            textColor = FOREGROUND_GREEN;
        } else if ( TYPE_CONSOLE == eLogType ) {
            // Cyan
            textColor = FOREGROUND_GREEN | FOREGROUND_BLUE;
        }
    } catch( ... ) {
         strStream << s_pLogger->m_strUnknownLogType;
    }

    // Date And Time
    if ( TYPE_CONSOLE != eLogType ) {
        SYSTEMTIME time;
        GetLocalTime( &time );

        strStream << " [" << time.wYear << "."
                  << std::setfill('0') << std::setw( 2 ) << time.wMonth << "."
                  << std::setfill('0') << std::setw( 2 ) << time.wDay << " "
                  << std::setfill(' ') << std::setw( 2 ) << time.wHour << ":"
                  << std::setfill('0') << std::setw( 2 ) << time.wMinute << ":"
                  << std::setfill('0') << std::setw( 2 ) << time.wSecond << "."
                  << std::setfill('0') << std::setw( 3 ) << time.wMilliseconds << "] ";
    }
    strStream << szText << std::endl;

    // Log Message
    SetConsoleTextAttribute( s_pLogger->m_hConsoleOutput, textColor );
    std::cout << strStream.str();

    // Save Message To Log File
    try {
        TextFileWriter file( s_pLogger->m_strLogFilename, true, false );
        file.write( strStream.str() );

    } catch( ... ) {
        // Not Saved In Log File, Write Message To Console
        std::cout << __FUNCTION__ << " failed to write to file: " << strStream.str() << std::endl;
    }

    // Reset To Default Color
    SetConsoleTextAttribute( s_pLogger->m_hConsoleOutput, s_pLogger->m_consoleDefaultColor );

}

} // namespace pro

FileHandler.h - 基类

#ifndef FILE_HANDLER_H
#define FILE_HANDLER_H

namespace pro {

// class AssetStorage; // Not Used Here

class FileHandler {
protected:
    // static AssetStorage* m_pAssetStorage; // Not Used Here

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

private:
    bool m_bSaveExceptionInLog;

public:
    virtual ~FileHandle();

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 pro

#endif // FILE_HANDLER_H

<强> FileHandler.cpp

#include "stdafx.h"
#include "FileHandler.h"
// #include "AssetStorage.h" // Not Used Here

namespace pro {

// AssetStorage* FileHandler::m_pAssetStorage = nullptr; // Not Used Here

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

    /*if ( bSaveExceptionInLog && nullptr == m_pAssetStorage ) {
        m_pAssetStorage = AssetStorage::get();
    }*/ // Not Used Here

    // 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() {
    if ( m_fileStream.is_open() ) {
         m_fileStream.close();
    }
}

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

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

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 Exists
        str = m_strFilePath + "/" + str;
    }

    return true;
}

} // namespace pro

现在您正在等待处理文件流的两个继承类。这两个是严格文本。我的项目中的其他人是TextureFiles,ModelObjectFiles等。我将只显示TextFileReader&amp; TextFileWriter。

<强> TextFileReader.h

#ifndef TEXT_FILE_READER_H
#define TEXT_FILE_READER_H

#include "FileHandler.h"

namespace pro {

class TextFileReader : public FileHandler {
private:
public:
    explicit TextFileReader( const std::string& strFilename );
    // virtual ~ TextFileReader(); // Default Okay

    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 pro

#endif // TEXT_FILE_READER_H

<强> TextFileReader.cpp

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

namespace pro {

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" ) );
}

std::string TextFileReader::readAll() const {
    std::ostringstream strStream;
    strStream << m_fileStream.rdbuf();
    return strStream.str();
}

bool TextFileReader::readLine( std::string& strLine ) {
    if ( m_fileStream.eof() ) {
        return false;
    }
    std::getline( m_fileStream, strLine );
    return true;
}

} // namespace pro

<强> TextFileWriter.h

#ifndef TEXT_FILE_WRITER_H
#define TEXT_FILE_WRITER_H

#include "FileHandler.h"

namespace pro {

class TextFileWriter : public FileHandler {
private:
public:
    TextFileWriter( const std::string& strFilename, bool bAppendToFile, bool bSaveExceptionInLog = true );

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

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

}; // TextFileWriter

} // namespace pro

#endif // TEXT_FILE_WRITER_H

<强> TextFileWriter.cpp

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

namespace pro {

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" ) );
    }
}

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

} // namespace pro

现在看一下这个实例的样本。如果查看Logger类,您将看到TextFileWriter的使用。

<强>的main.cpp

#include "stdafx.h"
#include "Logger.h"
#include "TextFileReader.h"
#include "TextFileWriter.h"

int _tmain( int iNumArguments, _TCHAR* pArgumentText[] ) {
    using namespace pro;

    try {
        // This Is Using The TextFileWriter & Console Output
        // Logger::TYPE_INFO is by default!
        Logger logger( "logger.txt" ); 
        logger.log( "Some Info" );
        logger.log( "Error!", Logger::TYPE_ERROR );
        logger.log( "Warning!", Logger::TYPE_WARNING );

        TextFileReader textReaderSingle( "logger.txt" );
        TextFileReader textReaderAll( "logger.txt" );

        std::string strTextSingle;
        std::string strTextAll;

        textReaderSingle.readLine( strTextSingle );
        std::cout << "Read Single Line: << std::endl << strText << std::endl << std::endl;

        strTextAll = textReaderAll.readAll();
        std::cout << "Read All: " << std::endl << strTextAll << std::endl;

        //Check The logger.txt that was generated in your projects folder!

        std::cout << "Press any key to quit" << std::endl;
        _getch();

    } catch ( ExceptionHandler& e ) {
        std::cout << "Exception Thrown: " << e.getMessage() << std::endl;
        std::cout << "Press any key to quit" << std::endl;
        _getch();
        return RETURN_ERROR;

    } catch( ... ) {
        std::cout << __FUNCTION__ << " Caught Unknown Exception" << std::endl;
        std::cout << "Press any key to quit" << std::endl;
        _getch();
        return RETURN_ERROR;
    }

    return RETURN_OK;
}

这项工作的大部分是由www.MarekKnows.com的MASc的Marek A. Krzeminski认可的。实质上所有这些类对象都是他的;唯一的主要区别是我使用自己的namespace pro而不是他的。两个main函数都是我自己的工作,第一个独立,第二个使用他的库代码。

这个项目已经开展了几年,我对C ++语言的大部分高级知识都是遵循他的视频教程。这个当前项目是一个相当大规模的专业品质GameEngine,使用OpenGL中的Shaders。所有这些都是在他的教程之后手动打字和调试的。

作为主要说明;我也曾在这里输入大部分内容,如果这不能正确编译,可能是由于印刷错误。它自己的源是一个工作的应用程序。你在这里看到的只是他作品的一小部分!我愿意接受这个问题,因为这些知识的积累可以回答这个人的问题,但我不能否认这是为了保护马立克及其版权材料而成为我自己的工作。

通过这种设置,可以很容易地为不同类型的文件创建自己的文件解析器和多个文件解析器。正如我上面所说,还有另外两个继承自FileHandler的类,我没有展示。如果您想了解更多此项目,请访问www.MarekKnows.com并加入社区。