如何在写入文件时忽略行

how to ignore lines when writing to a file

本文关键字:文件      更新时间:2023-10-16

如何在 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;
}

在"1.txt"中,我在第 4 行有"学生"一词,现在我想忽略上述 4 行,并在第 5 行(在"学生"一词下方(输入"输入"一词。当我运行上面的代码时,输出文件为空。任何建议如何解决这个问题?谢谢。

如果我

理解正确,您想要的只是 1.txt in 2.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自卫数据局.sdfg三1464BFGNDTY45y564格特格

输出文件 (2.txt( -

SDLFKNAS自卫数据局.sdfg输入1464BFGNDTY45y564格特格

附言为了更好地学习和理解编程,我建议不要使用:

using namespace std;

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

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

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

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

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

isalnum 函数在 <cctype> 中指定

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

#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() )将超出范围,它不会读取下一行,并且代码块在lineNumber == 5时永远不会输入您的if()语句,并且不会将文本"Input"打印到您的stream2文件流对象。

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

我的第一个答案解决了您的问题,并适当地将输出到您的文本文件中。但是,正如我提到的,用于读取一行文本并对两个文件流使用相同的计数器的 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 注意:并非所有这些包含和定义都将在这里使用,但这来自我的一个更大的项目,我只删除了这里需要的类,但保留我的标准标头。我从这个"stdafx.h"中删除的唯一内容是任何必须处理OpenGL,OpenAL,Ogg - Vorbis,GLM库和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

异常处理程序.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

块线程.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,因为在应用程序运行时,您只需要它的一个实例。

辛格尔顿

#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

辛格尔顿.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

记录器.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

记录器.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

文件处理程序.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和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

文本文件读取器.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

文本文件编写器.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的使用。

主.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++语言的大部分高级知识都是由于遵循他的视频教程。目前的这个项目是一个相当大规模的专业质量游戏引擎,使用OpenGL中的着色器。所有这些都是在按照他的教程进行操作时手动键入和调试的。

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

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