我试图检查文件是否已成功打开,从文件中读取并输出我从文件中读取的所有内容,因为我有7个文件需要在同一代码中进行操作,因此我想避免一遍又一遍地写相同的代码。
所以我做了一个bool
函数,并将其作为while
条件。
如果成功,该函数将返回true
,如果失败,则将返回false
。所以while(!function)
应该一直尝试直到它起作用,对吗?答案是肯定的,它可以按预期工作。
但是,如果我将while的条件更改为while(function)
,则可以期望重复执行该函数,直到它以某种方式失败(也许无法打开文件)。但它的行为不符合预期。它只能在第一次while
迭代中正常工作。
这是示例:
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <fstream>
#include <sstream>
bool readConfig(std::fstream& file, std::string (&str)[10], std::string identity) {
if(file.is_open()) {
if(file.seekg(0)) {
std::cout<<"Start from 0"<<std::endl;
}
// Get content line by line of txt file
int i = 0;
while(getline(file, str[i++]));
std::cout<<"i= "<<i<<std::endl;
for(int k = 0; k<i; k++) {
std::cout<<identity<<" = "<<str[k]<<std::endl;
}
return true;
} else {
std::cout<<"ERROR ! Could not open file."<<std::endl;
return false;
}
}
int main() {
char configFilePath[]="test.txt";
std::fstream configFile;
configFile.open(configFilePath, std::fstream::in);
std::string test[10];
std::string id = "testing";
while(!readConfig(configFile, test,id)) {
usleep(1000*1000);
};
return 0;
}
这是test.txt
的内容:
line 1
line 2
line 3
line 4
这是输出:
Start from 0
i= 5
testing = line 1
testing = line 2
testing = line 3
testing = line 4
testing =
i= 1
testing = line 1
i= 1
testing = line 1
以此类推。
为什么它在第一次迭代中起作用,然后在i=1
处停止?我问是因为我不知道自己做的事是否正确。 while(!function)
有效,但也许并非一直有效,也许我的代码有缺陷。
还是while(getline(configFile, string[i++]));
在这里错了?
这是我要替换的代码:
void readConfig(std::fstream& configFile, std::string (&str)[10], std::string identity) {
if(configFile) {
// Get content line by line of txt file
int i = 0;
while(getline(configFile, str[i++]));
//for debug only
if((i-1) == 0) {
std::cout<<identity<<" = "<<str[i-1]<<std::endl;
} else {
for(int k = 0; k<i-1; k++) {
std::cout<<identity<<" = "<<str[k]<<std::endl;
}
}
} else {
log("ERROR ! Could not get content from file.");
}
}
int main() {
file.open(file, std::fstream::in);
if(file.is_open()) {
std::cout<<"Successfully opened URL Display Text file."<<std::endl;
std::string inputs[10];
std::string id = "url_text";
readConfig(file, inputs, id);
file.close();
} else {
// Could not open file
log("Error ! Could not open file.");
}
}
我执行了7次,而不是仅仅调用一次函数7次,而这全部完成了。
答案 0 :(得分:1)
但是,如果我将while的条件更改为while(function),则可以期望重复执行该功能,直到它以某种方式失败(也许无法打开文件)。
您的推理在这里不对。该函数不会打开文件,因此在第一次迭代中成功进行下一次迭代时不会出错。
该函数的作用是:它读取文件的所有内容,然后返回true
。随后的迭代没有什么可读取的,但是函数仍然返回true
。
您应该检查文件是否仅打开一次,而不是在每次迭代中打开。如果该函数应该读取一行,那么请使其当前读取所有行。
答案 1 :(得分:1)
将测试从if (file.is_open())
更改为if (file)
。无法打开文件并不是文件流最终可能处于不良状态的唯一方法。特别是,在第二次调用此函数时,流是打开的,但由于上次读取尝试失败而处于失败状态。
答案 2 :(得分:0)
如果您只想逐行读取文件,打印并存储这些行,我会这样做。
std::vector
或std::array
在调用读取函数之前检查文件是否已打开
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
void readConfig(std::ifstream& configFile,
std::vector<std::string>& lines,
const unsigned int limit) {
std::string line;
while (std::getline(configFile, line)) {
if (lines.size() >= limit) {
break;
}
lines.push_back(line);
}
}
int main() {
const std::array<std::string, 3> fileNames = {"test1.txt",
"test2.txt",
"test3.txt"};
// Iterate over all your files
for (const auto& fileName : fileNames) {
// Open the file
std::ifstream configFile(fileName);
if (!configFile.is_open()) {
std::cout << "ERROR! Could not open file.\n";
continue;
}
// Read the file
std::vector<std::string> lines;
constexpr unsigned int limit = 4;
readConfig(configFile, lines, limit);
if (configFile.is_open()) {
configFile.close();
}
// Work with the file content
std::cout << fileName << "\n";
for (const auto& line : lines) {
std::cout << "testing = " << line << "\n";
}
std::cout << "\n";
}
return 0;
}
答案 3 :(得分:0)
您的输出可以清楚地显示正在发生的事情。您有足够的调试输出来确定已做出的选择。我要重点介绍的重点是以下顺序:
testing = i= 1
第一行是从四行文件中读取的第五行。毫不奇怪,那里什么都没有。下一条输出行来自readConfig
在分支file.isopen()
为true的某处的下一次调用。但是,请注意,在这两个之间没有 not 一行,表示“从0开始”。这意味着file
在调用false
之后转换为file.seekg(0)
(该函数返回的值为file
,而不是直接的布尔值)。这表明存在某种错误状态,应该期望该错误状态持续存在直到清除。而且没有尝试清除它。
代码的下一部分是getline
循环。与seekg
一样,getLine
函数返回流(file
)而不是布尔值。如预期的那样,错误状态一直存在,从而使循环成为false
,因此没有循环迭代。
testing = line 1
输出的下一行是不明确的。这可能表明位置已成功更改为文件的开头,并且输入的第一行已成功读取。或者它可能指示在删除提供的字符串之前返回对getLine
的调用,而将第一次调用中的内容留给readConfig
。我正在考虑使用后者,但是您可以通过在str[0]
循环之前手动擦除getline
来进行检查。
通常,这样重复使用资源会使调试更加困难,因为结果可能会产生误导。如果str
是局部变量而不是参数,则调试的混乱程度将降低。与file
类似-除了可以使用流参数之外,您还可以传递带有要打开文件名称的字符串。