From 485bab3b48118d4e0dfbabeb4890eabad3ad2e0c Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Thu, 24 Jul 2014 10:41:20 +0200 Subject: [PATCH] Made text file reading more efficient and robust Instead of reading the file line by line and then concatenating those lines, just load the entire thing in one go. And pay more attention to error conditions. --- src/gmenu2x.cpp | 48 +++++++++++++++-------------------------------- src/linkapp.cpp | 15 +++------------ src/utilities.cpp | 25 ++++++++++++++++++++++++ src/utilities.h | 3 +++ 4 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/gmenu2x.cpp b/src/gmenu2x.cpp index 08ff48e..232b136 100644 --- a/src/gmenu2x.cpp +++ b/src/gmenu2x.cpp @@ -409,45 +409,27 @@ void GMenu2X::initMenu() { } void GMenu2X::about() { - string str, line; - string fn(GMENU2X_SYSTEM_DIR); - string build_date("Build date: "); - fn.append("/about.txt"); - build_date.append(__DATE__); - - ifstream inf(fn.c_str(), ios_base::in); - - while(getline(inf, line, '\n')) { - str.append(line).append("\n"); - } - inf.close(); - - TextDialog td(this, "GMenu2X", build_date, "icons/about.png", str); + string text(readFileAsString(GMENU2X_SYSTEM_DIR "/about.txt")); + string build_date("Build date: " __DATE__); + TextDialog td(this, "GMenu2X", build_date, "icons/about.png", text); td.exec(); } void GMenu2X::viewLog() { - string logfile = LOG_FILE; - if (fileExists(logfile)) { - ifstream inf(logfile.c_str(), ios_base::in); - if (inf.is_open()) { - string str, line; - while (getline(inf, line, '\n')) { - str.append(line).append("\n"); - } - inf.close(); + string text(readFileAsString(LOG_FILE)); - TextDialog td(this, tr["Log Viewer"], tr["Displays last launched program's output"], "icons/ebook.png", str); - td.exec(); + TextDialog td(this, tr["Log Viewer"], + tr["Displays last launched program's output"], + "icons/ebook.png", text); + td.exec(); - MessageBox mb(this, tr["Do you want to delete the log file?"], "icons/ebook.png"); - mb.setButton(InputManager::ACCEPT, tr["Yes"]); - mb.setButton(InputManager::CANCEL, tr["No"]); - if (mb.exec() == InputManager::ACCEPT) { - unlink(logfile.c_str()); - menu->deleteSelectedLink(); - } - } + MessageBox mb(this, tr["Do you want to delete the log file?"], + "icons/ebook.png"); + mb.setButton(InputManager::ACCEPT, tr["Yes"]); + mb.setButton(InputManager::CANCEL, tr["No"]); + if (mb.exec() == InputManager::ACCEPT) { + unlink(LOG_FILE); + menu->deleteSelectedLink(); } } diff --git a/src/linkapp.cpp b/src/linkapp.cpp index 3ab9aae..a8baa6a 100644 --- a/src/linkapp.cpp +++ b/src/linkapp.cpp @@ -491,18 +491,9 @@ void LinkApp::showManual() { // Txt manuals if (manual.substr(manual.size()-8,8)==".man.txt") { - string str, line; - ifstream infile(manual.c_str(), ios_base::in); - if (infile.is_open()) { - while (getline(infile, line, '\n')) { - str.append(line).append("\n"); - } - infile.close(); - - TextManualDialog tmd(gmenu2x, getTitle(), getIconPath(), str); - tmd.exec(); - } - + string text(readFileAsString(manual.c_str())); + TextManualDialog tmd(gmenu2x, getTitle(), getIconPath(), text); + tmd.exec(); return; } diff --git a/src/utilities.cpp b/src/utilities.cpp index c85fff0..4ff4075 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -56,6 +56,31 @@ string rtrim(const string& s) { return e == string::npos ? "" : string(s, 0, e + 1); } +// See this article for a performance comparison of different approaches: +// http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html +string readFileAsString(const char *filename) { + ifstream in(filename, ios::in | ios::binary); + if (!in) { + return ""; + } + + // Get file size. + in.seekg(0, ios::end); + auto size = max(int(in.tellg()), 0); // tellg() returns -1 on errors + in.seekg(0, ios::beg); + + string contents(size, '\0'); + in.read(&contents[0], contents.size()); + in.close(); + + if (in.fail()) { + return ""; + } else { + contents.shrink_to_fit(); + return contents; + } +} + bool fileExists(const string &file) { fstream fin; fin.open(file.c_str() ,ios::in); diff --git a/src/utilities.h b/src/utilities.h index aa29308..d9f235d 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -46,6 +46,9 @@ std::string ltrim(const std::string& s); /** Returns the string with whitespace stripped from the end. */ std::string rtrim(const std::string& s); +/** Returns the contents of the given file as a string. */ +std::string readFileAsString(const char *filename); + std::string strreplace(std::string orig, const std::string &search, const std::string &replace); std::string cmdclean(std::string cmdline);