【问题标题】:Adding a method to an existing class to read contents of file line by line向现有类添加方法以逐行读取文件内容
【发布时间】:2019-10-23 03:23:56
【问题描述】:

我知道有很多类似的问题被问到,例如:

但是,我有一个已经存在的类,它具有我不想破坏的特定行为,我想做的是为这个类添加一个额外的函数。

我正在处理的当前类是一个基本的TextFileReader 类,它继承自FileHandler 类。我将显示当前的类层次结构,以便您可以看到我已经拥有的内容:您可以忽略使用的ExceptionHandler,因为它与这个问题无关,但我把它留在这里,因为这是我的类的定义方式。


FileHandler.h

#pragma once

#include <string>
#include <sstream>
#include <fstream>

namespace util {

    class FileHandler {
    protected:
        std::fstream    fileStream_;
        std::string     filePath_;
        std::string     filenameWithPath_;

    private:
        bool saveExceptionInLog_;

    public:
        virtual ~FileHandler();

        FileHandler(const FileHandler& c) = delete;
        FileHandler& operator=(const FileHandler& c) = delete;

    protected:
        FileHandler(const std::string& filename, bool saveExceptionInLog);

        void throwError(const std::string& message) const;
        void throwError(const std::ostringstream& streamMessage) const;
    };

} // namespace util

FileHandler.cpp

#include "FileHandler.h"
#include "ExceptionHandler.h"

using namespace util;

FileHandler::FileHandler(const std::string & filename, bool saveExceptionInLog) :
    saveExceptionInLog_(saveExceptionInLog),
    filenameWithPath_(filename) {
    // Extract path info if it exists
    std::string::size_type lastIndex = filename.find_last_of("/\\");
    if (lastIndex != std::string::npos) {
        filePath_ = filename.substr(0, lastIndex);
    }

    if (filename.empty()) {
        throw ExceptionHandler(__FUNCTION__ + std::string(" missing filename", saveExceptionInLog_));

    }
}

FileHandler::~FileHandler() {
    if (fileStream_.is_open()) {
        fileStream_.close();
    }
}

void FileHandler::throwError(const std::string & message) const {
    throw ExceptionHandler("File [" + filenameWithPath_ + "] " + message, saveExceptionInLog_);
}

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

TextFileReader.h

#pragma once

#include "FileHandler.h"

namespace util {

    class TextFileReader : public FileHandler {
    public:
        explicit TextFileReader(const std::string& filename);
        virtual ~TextFileReader() = default;

        TextFileReader(const TextFileReader& c) = delete;
        TextFileReader& operator=(const TextFileReader& c) = delete;

        std::string readAll() const;    

    };

} // namespace util

TextFileReader.cpp

#include "TextFileReader.h"

using namespace util;

TextFileReader::TextFileReader(const std::string & filename) :
FileHandler( filename, true ) {
    fileStream_.open(filenameWithPath_.c_str(), std::ios_base::in);
    if (!fileStream_.is_open()) {
        throwError(__FUNCTION__ + std::string(" can not open file for reading"));
    }
}

std::string TextFileReader::readAll() const { 
    std::ostringstream stream;
    stream << fileStream_.rdbuf();

    return stream.str();
}

我想做或者我正在尝试做的是将这个方法添加到我的TextFileReader

std::vector<std::string> readLineByLine() const;

我已经尝试了我在上面这个问题开头列出的原始问答中的几种方法。

我遇到的一些问题是,在基类中我存储的是 fstream 对象而不是 ifstreamofstream 对象,因此尝试在循环中使用 std::getline 不是在职的。我试图直接从文件流句柄中逐行读取。

在我的下一次尝试中,我尝试重用已经存在的readAll() 并将文件的所有内容读入单个缓冲区并将其作为单个字符串返回,然后将该字符串解析为字符串向量。在我的while循环中的这种方法中,我仍然无法使用std::getline,因为它使用的是ostringstream对象而不是istringstream对象。


函数应该像这样工作 - 伪代码:

std::vector<std::string> TextFileReader::readLineByLine() const {
    // get contents from file either line by line and store
    // each line into a string and push that string into a
    // vector of strings then return that vector after all 
    // lines have been read.

   // or...

   // read all contents from file into single string buffer and parse
   // that string into a vector of strings and return that vector.
}

这就是我遇到问题的地方。有什么建议吗?

编辑

我最初尝试了用户的 Bapo's 方法,但我得到了这个编译器错误:

1>------ Build started: Project: ChemLab, Configuration: Debug Win32 ------
1>TextFileReader.cpp
1>c:\...\textfilereader.cpp(24): error C2665: 'std::getline': none of the 2 overloads could convert all the argument types
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\string(160): note: could be 'std::basic_istream<char,std::char_traits<char>> &std::getline<char,std::char_traits<char>,std::allocator<char>>(std::basic_istream<char,std::char_traits<char>> &,std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\string(129): note: or       'std::basic_istream<char,std::char_traits<char>> &std::getline<char,std::char_traits<char>,std::allocator<char>>(std::basic_istream<char,std::char_traits<char>> &&,std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)'
1>c:\...\textfilereader.cpp(24): note: while trying to match the argument list '(const std::fstream, std::string)'
1>Done building project "ChemLab.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

但是,一位用户评论说,如果我将fileStream_ 设为可变,则 const 函数将不起作用。我继续将 mutable 修饰符添加到 fileStream_ 成员,现在函数编译了。

【问题讨论】:

    标签: c++ file stream c++17


    【解决方案1】:

    你可以做这样简单的事情:

    std::vector<std::string> TextFileReader::readLineByLine() {
        std::vector<std::string> return_vector{};
        std::string line;
        while(std::getline(fileStream_, line)) {
            return_vector.push_back(line);
        }
        return return_vector;
    
    }
    

    但是,在此之后,您的整个流将被读取,并且将是“空的”

    编辑:忘记实际返回向量。

    【讨论】:

    • 我试图将我的fileStream_ 传递给getline,但它没有编译......哦,我忘了提到我的函数定义应该是 const,我将我的问题编辑为反映这一点。
    • 我说过我已经尝试过这种方法。我完全尝试了您向我展示的内容,但出现编译器错误,我会将其附加到我的问题中。
    • @FrancisCugler:不可能是const。你在操纵一个成员。这不是const 操作。
    • @FrancisCugler “哦,我忘了说我的函数声明应该是 const,” 除非你使用 fileSream_ mutable 你不能用 @ 987654328@ 功能。从文件中读取意味着改变实例的状态。
    • 你知道“可变”关键字的作用吗?它允许您在结构本身为 const 时编辑这些成员,这意味着您可以在拥有 const 方法时从文件中读取。
    猜你喜欢
    • 2022-08-22
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    • 1970-01-01
    • 2018-06-10
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    相关资源
    最近更新 更多