使用 boost::filesystem,如何防止覆盖以前的密码文件?
Using boost::filesystem, how can I prevent overwriting of previous password files?
好的,我对 C++ 和一般编码还很陌生。我正在研究一个密码生成器,它随机生成一个介于 33 和 126 之间的数字,然后使用相应的 ASCII 代码并创建一个用户指定长度的密码。然后我想使用 boost::filesystem 创建一个密码文件夹,并在该文件夹中使用 std::ofstream 创建一个包含密码的文本文件。我已经弄清楚如何创建文件夹,以及如何创建文件。但是......我需要一种方法来确定文件夹中是否已经存在密码文件,如果是,则按数字顺序创建不同名称的密码文件(因为写入文件会覆盖以前的密码)。例如,如果我要 运行 程序三次,在密码文件夹中将有三个文件,分别命名为 '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
, along with other operations for querying 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。从 C11 开始,fopen
允许在文件打开模式中指定“x”以指示如果文件存在则该函数必须失败。您必须咨询您的编译器或标准 C 库文档,看看它是否支持这个新增功能。
或者,您可以使用低级文件系统 API,例如 open
call with O_CREAT
and O_EXCL
flags on POSIX systems or CreateFile
和 Windows 上的 CREATE_NEW
标志。
几个不相关的笔记。
您不需要 static_cast<std::string>(array)
将 C-style 字符串输出到流。直接输出一个字符数组是可行的——数组中的字符将被写入流中,直到第一个空字符(终止符)。通过强制转换,您只是不必要地分配动态内存并在输出之前复制字符串。
避免在函数参数中按值接受潜在的大对象,如容器、字符串或路径,除非函数体需要。您的 fs::path dir
参数可以更好地被接受为常量引用 (fs::path const& dir
),这可能会避免在调用 savePassword
.
时必须复制路径
好的,我对 C++ 和一般编码还很陌生。我正在研究一个密码生成器,它随机生成一个介于 33 和 126 之间的数字,然后使用相应的 ASCII 代码并创建一个用户指定长度的密码。然后我想使用 boost::filesystem 创建一个密码文件夹,并在该文件夹中使用 std::ofstream 创建一个包含密码的文本文件。我已经弄清楚如何创建文件夹,以及如何创建文件。但是......我需要一种方法来确定文件夹中是否已经存在密码文件,如果是,则按数字顺序创建不同名称的密码文件(因为写入文件会覆盖以前的密码)。例如,如果我要 运行 程序三次,在密码文件夹中将有三个文件,分别命名为 '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
, along with other operations for querying 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。从 C11 开始,fopen
允许在文件打开模式中指定“x”以指示如果文件存在则该函数必须失败。您必须咨询您的编译器或标准 C 库文档,看看它是否支持这个新增功能。
或者,您可以使用低级文件系统 API,例如 open
call with O_CREAT
and O_EXCL
flags on POSIX systems or CreateFile
和 Windows 上的 CREATE_NEW
标志。
几个不相关的笔记。
您不需要
static_cast<std::string>(array)
将 C-style 字符串输出到流。直接输出一个字符数组是可行的——数组中的字符将被写入流中,直到第一个空字符(终止符)。通过强制转换,您只是不必要地分配动态内存并在输出之前复制字符串。避免在函数参数中按值接受潜在的大对象,如容器、字符串或路径,除非函数体需要。您的
时必须复制路径fs::path dir
参数可以更好地被接受为常量引用 (fs::path const& dir
),这可能会避免在调用savePassword
.