如何解决使用boost :: filesystem,如何防止覆盖以前的密码文件?
好的,我对C ++和编码一般还是陌生的。我正在使用一个密码生成器,该密码生成器随机生成一个介于33和126之间的数字,然后使用相应的ASCII码并创建用户指定长度的密码。然后,我想使用boost :: filesystem创建一个密码文件夹,并在该文件夹中使用std :: ofstream创建一个包含密码的文本文件。我已经弄清楚了如何创建文件夹以及如何创建文件。但是...我需要一种方法来确定文件夹中是否已经有密码文件,如果有,请按数字顺序创建名称不同的密码文件(因为写入文件会覆盖以前的密码)。例如,如果我要运行该程序3次,则passwords文件夹中将包含三个文件,分别名为“ password.txt”,“ password2.txt”和“ password3.txt”。这是我到目前为止的内容:
namespace fs = boost::filesystem;
void savePassword(char array[],fs::path dir)
{
std::cout << "Saving...\n";
//this is where there needs to be a check,and the check needs to return how many password files there are
std::ofstream savePw;
savePw.open("./Passwords/password.txt"); //check to see if file exists before this,if so,make it "./Passwords/password" += number of files += ".txt"
if (!savePw) {
std::cout << "ERROR: File could not be opened.\n";
}
else {
savePw << "Your password is:\n" << static_cast<std::string>(array) << '\n';
savePw.close();
std::cout << "Saved to: " << dir << '\n' << "Thanks for using the SPG!\n";
}
}
fs::path createFolder() //creates folder and returns the directory to be passed to savePassword()
{
fs::path dir{ boost::dll::program_location().parent_path() += "\\Passwords" };
fs::create_directory(dir);
return dir;
}
做了很多研究,但还没有真正发现任何东西。我已经尝试了boost :: filesystem :: directory_iterator,但是并不太了解如何使用它。我也尝试过将路径转换为字符串并使用std :: stoi,但这是失败的。任何帮助深表感谢。 :)
解决方法
Boost.Filesystem提供了名为exists
的操作,以及用于查询文件status的其他操作。您可以使用如下所示的循环生成文件名:
fs::path generate_filename(fs::path const& dir)
{
fs::path path = dir / "password.txt";
unsigned int counter = 1u;
while (true)
{
if (!fs::exists(path))
break;
++counter;
if (counter == 0u)
throw std::runtime_error("Failed to generate a unique file name");
path = dir / std::string("password")
.append(std::to_string(counter)).append(".txt");
}
return path;
}
但是,请注意该代码是合理的,因为可以在调用exists
和打开文件进行写入之间创建文件。解决方案是在打开文件时测试文件是否存在。
从C ++ 20开始,标准C ++文件流不允许在打开文件进行写入时测试文件是否存在,因此您将不得不使用其他文件API。以{11}开头的C {11}允许在文件打开模式下指定“ x”,以表明该功能必须在文件存在的情况下失败。您必须查阅编译器或标准C库文档,以查看其是否支持此新增功能。
或者,您可以使用低级文件系统API,例如在POSIX系统上使用O_CREAT
和O_EXCL
标志进行fopen
调用,或使用带有CREATE_NEW
标志的open
在Windows上。
一些不相关的笔记。
-
您不需要
static_cast<std::string>(array)
即可将C样式的字符串输出到流中。直接输出字符数组将起作用-数组中的字符将被写入流,直到第一个空字符(终止符)为止。通过强制转换,您不必分配动态内存并在输出之前复制字符串。 -
除非函数体要求,否则请避免按值在函数参数中接受可能较大的对象,例如容器,字符串或路径。您最好将
fs::path dir
参数作为const引用(fs::path const& dir
)接受,这样可以避免在调用savePassword
时必须复制路径。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。