Это не является ответом на ППО вопрос, а скорее он предоставляется для небольшого разговора в серии комментариев о чтении файлов и анализе данных. Это направлено на Тони и всех, кто хотел бы использовать эту установку класса. В этом классе есть некоторые вещи, которые относятся к другим классам в моей библиотеке, некоторые из которых включают в себя мой Logger, который будет регистрировать сообщения либо в файле, либо в консоли, а типы сообщений - это Info, Warning, Error или Console. Мой регистратор получен из класса Singleton, так как для обработки всех сообщений мне понадобится только один регистратор на одно решение. У меня есть класс Utility, который обрабатывает большинство функций манипуляции строками, где конструктор является закрытым, а все функции или члены объявляются как статические. Этот класс также полагается на класс ExceptionHandler, который будет принимать объекты std :: strings или std :: ostringstream. Мой Logger принимает то же самое. Кроме того, некоторые из моих классов также полагаются на класс BlockThread, который позволяет работать с многопоточным процессом, который после построения будет создавать и инициализировать CriticalSection, а затем вводить критический раздел, а затем после уничтожения он уйдет, а затем уничтожит CriticalSection. Теперь, что касается этой демонстрации, я буду показывать только классы FileHandler вместе с двумя ее производными типами 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.каст
#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.
Это заголовок класса, в котором используется FileHandler. Он читает в текстовом файле и анализирует его, чтобы определить, какие объекты GUI создавать, загружать в память и как они должны отображаться на экране, а также накладывать один GUI типа в качестве ребенка другому. Я не буду показывать полную реализацию этого класса, но только несколько функций, где это касается использования 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
Это было представлено, чтобы показать надежность моих классов обработки файлов. Здесь не так много других классов. Моя библиотека является частью библиотеки 3D-рендеринга, которая использует Modern OpenGL. Существует несколько сотен объектов класса и 100 000 строк кода для выполнения 3D-рендеринга, загрузки спрайтов, моделирования физики, анимации, воспроизведения звука, воспроизведения аудиопотока и многое другое. Не весь этот исходный код имеет мою собственную конструкцию, поэтому этот код защищен Marek A. Krzeminski, MASc, а его работы можно найти по адресу: www.MarekKnows.com
Весь код, показанный здесь, не был скопирован и вставлен с его сайта, все это было напечатано вручную, а затем сопровождалось его видеоуроками. Он был скомпилирован и отлажен вручную. Этот проект работает в течение нескольких лет, и до сих пор добавляется еще больше. Я с гордостью отношусь к его веб-сайту и сообществу с 2007 по 2008 год.
Почему вы думаете, что это может быть невозможно? –
, потому что я протестировал код, почти похожий на этот .. и когда я это сделал. Я получил нули – Nathan
Проверьте файл, чтобы увидеть, есть ли какие-либо '0' s. Если это так, это не код ввода, который закручивается, это код вывода. Кроме того, убедитесь, что вы устанавливаете 'rand' вправо, используя' srand() '. –