这里说C++风格的文件操作,也就是<fstream>库里面的使用(ifstream/ostream)。
(1)删除某一特定行
思想:首先你需要有方法找到你要删除的那一行是哪一行,然后逐一遍历文件的每一行,并用一个临时string变量(网上有另一个方法是新开一个暂存文件)存储,判断如果是要是删除的那一行,就不要把该行存到string临时变量中,也就是跳过该行,继续遍历到文件尾不能get到内容为止。此时,已经把文件里面除了要删除那行的其他所有行都暂存了,于是把原文件所有内容清空(ios::trunc),清空完之后再把临时string变量存储的东西再放入文件,关闭文件,就达到了删除特定行的效果。
void dele()
{
cout << "请输入要删除的域名" << endl;
string domain;
cin >> domain;
string temp,d,h,p,pp;
string _filename = filename + ".txt";
ifstream infile(_filename);
int t = find(domain);
if (t != -1)
{
getline(infile, pp);
temp += pp + "
";
int count = countLines();
for (int i = 2; i <= count; i++)
{
if (i != t)
{
get_content(i, d, h, p);
//infile >> d >> h >> p;
temp += d + " " + h + " " + p + "
";
}
}
infile.close();
//remove(_filename.c_str());//先删除原文件
ofstream outfile(_filename, ios::trunc);//ios::trunc打开一个文件,然后清空内容
//cout << temp << endl;
outfile << temp;
outfile.close();
cout << "删除成功" << endl;
}
else
{
infile.close();
cout << "未找到相应的记录!" << endl;
dele();
}
key_manage();
}
这里获取每一行的内容我是把功能封装成一个特定的函数get_content了,方便项目其他地方的操作。
const bool get_content(int line,string &domain,string &domain_hash,string &password)//line表示获取第几行的域名+内容
{
if (line <= 0)
{
return false;
}
string _filename = filename + ".txt";
//ifstream infile(_filename,ios::in);//ios:in表示以只读方式打开文件
ifstream infile(_filename,ios::in);
if (infile.fail())
{
cout << "打开文件失败!" << endl;
return false;
}
int count = countLines();
int i = 1;
string temp;
if (line>count)
{
cout << "超出行数" << endl;
infile.close();
return false;
}
while (i < line)//移动文件指针
{
getline(infile, temp);
i++;
}
infile >> domain >> domain_hash >> password;//注意这里是读取下一行!所以上面要在line-1就停止
infile.close();
return true;
}
ifstream infile(_filename,ios::in);//ios:in表示以只读方式打开文件
又如这样打开时直接把文件指针定位到文件尾,然后在文件最后新开一行存储内容:
void fileInput(string domain, string domain_hash, string encryPass)
{
string _filename = filename + ".txt";
ofstream outfile(_filename, ios::app); //ios::app 添加到文件尾;ios::ate 把文件标志放在末尾而非起始
outfile << domain << " " << domain_hash << " " << encryPass << endl;
outfile.close();
}
关于打开参数这里有篇别人的博客供详细参考:
(2)计算文件内容总行数:
<pre name="code" class="cpp">int countLines()
{
ifstream infile(filename+".txt");
if (infile.fail())
{
cout << "打开文件失败!" << endl;
abort();
}
int count = 0;
string temp;
while (getline(infile, temp, '
'))
{
count++;
}
infile.close();
return count;
}
(3)找文件里的内容:
int find(string domain)
{
int count = countLines();
for (int i = 2; i <= count; i++)
{
string d, h, p;
bool test = get_content(i, d, h, p);
if (test)
{
if (domain == d)
return i;
}
}
return -1;//找不到就返回-1
}
我这里是按照域名从第二行(因为第一行存的是别的东西)开始找,匹配到就返回所在行的下标。
(4)替换文件内容:
跟删除差不多的操作,也是记录所在行,但是替换的话是要把包括该行也记录下来,只不过记录的内容要替换成新的,然后也是清空文件再放临时变量的内容进去:
void modify()
{
cout << "请输入要修改密码的相应域名" << endl;
string domain;
cin >> domain;
string _filename = filename + ".txt";
ifstream infile(_filename);
int t = find(domain);
if (t != -1)
{
cout << "请输入新密码" << endl;
string newPass;
cin >> newPass;
string key = get_key();
string newPassword = AES_Encryption(newPass, key);//把新密码拿去加密
string d, h, p, temp, pp;
getline(infile, pp);
temp += pp + "
";
int count = countLines();
for (int i = 2; i <= count; i++)
{
get_content(i, d, h, p);
if (i != t)
{
temp += d + " " + h + " " + p + "
";
}
else// i == t
{
temp += d + " " + h + " " + newPassword + "
";
}
}
infile.close();
//remove(_filename.c_str());//先删除原文件
ofstream outfile(_filename, ios::trunc);//ios::trunc打开一个文件,然后清空内容
//cout << temp << endl;
outfile << temp;
outfile.close();
}
else
{
infile.close();
cout << "未找到相应的记录!" << endl;
modify();
}
key_manage();
}