C ++如何为多个文件编写ifstream?
C++ how to write a ifstream for multiple files?
所以我有几个文件,它们的行数各不相同,所以我们称它们为 file1、file2、file3 等等。我想要做的是创建一个 istream class 来流式传输所有文件,就好像它们是一个文件一样。我得到的一件事不是 subclass std::istream 而是重新实现 streambuf。我的问题是:我将如何解决这个问题 - 我如何能够在不将它们全部存储在内存中的情况下从多个文件中读取?
是否可以制作一个读取多个文件的istream
?
是的,但您必须自己制作。你可以通过扩展std::istream
实现你自己的istream
class,然后实现它定义的方法:
class custom_istream : public std::istream {
std::ifstream underlying;
//... implement methods
};
std::istream
的界面非常灵活,可以让您随心所欲。 但是,实施std::istream
需要大量工作,因为您必须实施整个接口。
有没有更简单的解决方案?
如果您只需要 std::istream
提供的部分功能,您可以自己编写 class。
例如,如果您只需要能够从文件中读取行,下面的 class 将适用于多个文件:
class MultiFileReader {
std::ifstream filestream;
std::ios_base::openmode mode;
size_t file_index = 0;
std::vector<std::string> filenames;
void open_next_file() {
file_index++;
filestream = std::ifstream(filenames.at(file_index), mode);
}
public:
MultiFileReader(std::vector<std::string> const& files, std::ios_base::openmode mode)
: filestream(files[0], mode), mode(mode) {}
// Checks if there's no more files to open, and no more to read
// in the current file
bool hasMoreToRead() {
if(file_index == filenames.size()) return false;
if(file_index + 1 == filenames.size())
return not filestream.eof();
return true;
}
std::string read_line() {
if(not hasMoreToRead()) {
throw std::logic_error("No more to read");
}
// If at the end of the file, open the next file
if(filestream.eof()) {
open_next_file();
}
else {
std::string line;
std::getline(filestream, line);
return line;
}
}
};
所以我有几个文件,它们的行数各不相同,所以我们称它们为 file1、file2、file3 等等。我想要做的是创建一个 istream class 来流式传输所有文件,就好像它们是一个文件一样。我得到的一件事不是 subclass std::istream 而是重新实现 streambuf。我的问题是:我将如何解决这个问题 - 我如何能够在不将它们全部存储在内存中的情况下从多个文件中读取?
是否可以制作一个读取多个文件的istream
?
是的,但您必须自己制作。你可以通过扩展std::istream
实现你自己的istream
class,然后实现它定义的方法:
class custom_istream : public std::istream {
std::ifstream underlying;
//... implement methods
};
std::istream
的界面非常灵活,可以让您随心所欲。 但是,实施std::istream
需要大量工作,因为您必须实施整个接口。
有没有更简单的解决方案?
如果您只需要 std::istream
提供的部分功能,您可以自己编写 class。
例如,如果您只需要能够从文件中读取行,下面的 class 将适用于多个文件:
class MultiFileReader {
std::ifstream filestream;
std::ios_base::openmode mode;
size_t file_index = 0;
std::vector<std::string> filenames;
void open_next_file() {
file_index++;
filestream = std::ifstream(filenames.at(file_index), mode);
}
public:
MultiFileReader(std::vector<std::string> const& files, std::ios_base::openmode mode)
: filestream(files[0], mode), mode(mode) {}
// Checks if there's no more files to open, and no more to read
// in the current file
bool hasMoreToRead() {
if(file_index == filenames.size()) return false;
if(file_index + 1 == filenames.size())
return not filestream.eof();
return true;
}
std::string read_line() {
if(not hasMoreToRead()) {
throw std::logic_error("No more to read");
}
// If at the end of the file, open the next file
if(filestream.eof()) {
open_next_file();
}
else {
std::string line;
std::getline(filestream, line);
return line;
}
}
};