- 情景
用fstream打开一个文件,在关闭之前,可以删除该文件和其所在的目录吗?
- 结论
linux下,可以删除已打开文件和其所在目录,且对已存在的fstream读写操作无影响。但win下不行,有时notepad打开的文件可以删除,那是notepad会实时关闭文件。
- 验证
我们实现一个类FileTest,该类有如下功能
- 构造函数,分别以读写的方式打开该文件
- 析构函数,关闭文件
- Write函数,写文件
- Read函数,读文件,读取Write写入的内容
- RemovePath函数,删除文件
- RemoveDir函数,删除文件所在目录
- TestRemovePath函数,测试文件被打开时,能否删除文件,以及删除文件后Read还能不能读取到Read的内容
- TestRW_AfterRmovePath函数,连续调用两次TestRemovePath
- TestRemoveDir函数,测试文件被打开时,能否删除文件所在目录,以及删除目录后Read还能不能读取到Read的内容
#include<fstream>
#include <iostream>
#include<stdio.h>
#include<chrono>
#include<string>
#define log_debug(...) do{printf(__VA_ARGS__);printf("\n");}while(0)
class FileTest {
public:
FileTest(const std::string &dir, const std::string &fname) :m_dir(dir), m_fpath(dir+fname) {
m_ofs.open(m_fpath);
m_ifs.open(m_fpath);
if (!m_ofs || !m_ifs) {
log_debug("FileTest::FileTest init fpath err,fpath=%s", m_fpath.c_str());
m_is_valid = false;
}
else{
log_debug("FileTest::FileTest init fpath okay,fpath=%s",m_fpath.c_str());
m_is_valid = true;
}
}
~FileTest() {
m_ofs.close();
m_ifs.close();
}
void Write() {
if (!m_is_valid) return;
if (m_ofs.bad())
log_debug("FileTest::Write error,file is bad");
auto before = m_ofs.tellp();
m_ofs << m_test_str;
m_ofs.flush();
if ((m_ofs.tellp() - before) != m_test_str.size())
log_debug("FileTest::Write wrong num,write=%d", m_ofs.tellp() - before);
else
log_debug("FileTest::Write okay");
}
void Read() {
if (!m_is_valid) return;
if (m_ifs.bad())
log_debug("FileTest::Read error,file is bad");
std::string str;
str.resize(m_test_str.size());
m_ifs.read(const_cast<char*>(str.data()),str.size());
if (str != m_test_str)
log_debug("FileTest::Read error,str error,str=%s", str.c_str());
else
log_debug("FileTest::Read okay");
}
void RemovePath() {
if (!m_is_valid) return;
if (std::remove(m_fpath.c_str()) != 0)
log_debug("FileTest::RemoveFpath error");
else
log_debug("FileTest::RemoveFpath okay");
}
void RemoveDir() {
if (!m_is_valid) return;
if (std::remove(m_dir.c_str()) != 0)
log_debug("FileTest::RemoveDir error");
else
log_debug("FileTest::RemoveDir okay");
}
void TestRemovePath() {
Write();
RemovePath();
Read();
}
void TestRemoveDir() {
Write();
RemoveDir();
Read();
}
void TestRW_AfterRmovePath() {
TestRemovePath();
TestRemovePath();
}
const std::string &Dir()const { return m_dir; }
const std::string &Path()const { return m_fpath; }
private:
std::string m_dir;
std::string m_fpath;
std::ofstream m_ofs;
std::ifstream m_ifs;
const std::string m_test_str = "hello";
bool m_is_valid = true;
};
int main(int argc, char *argv[])
{
#ifdef WIN32
FileTest ft("D:\\tmp\\test\\","a.txt");
#else
FileTest ft("/root/test/", "a.txt");
#endif
ft.TestRW_AfterRmovePath();
ft.TestRemoveDir();
return 0;
}
linux结果
root@VM-0-15-ubuntu:~# ./a.out
FileTest::FileTest init fpath okay,fpath=/root/test/a.txt
FileTest::Write okay
FileTest::RemoveFpath okay
FileTest::Read okay
FileTest::Write okay
FileTest::RemoveFpath error
FileTest::Read okay
FileTest::Write okay
FileTest::RemoveDir error
FileTest::Read okay
win结果
FileTest::FileTest init fpath okay,fpath=D:\tmp\test\a.txt
FileTest::Write okay
FileTest::RemoveFpath error
FileTest::Read okay
FileTest::Write okay
FileTest::RemoveFpath error
FileTest::Read okay
FileTest::Write okay
FileTest::RemoveDir error
FileTest::Read okay
std::remove
细心的读者发现,linux下没有成功删除目录,那是因为std::remove只能删除文件或空目录,非空目录不能删除。
下面是cppreference中,对std::remove的解释。
那么如果我们想要删除非空目录该怎么办呢?c++较高版本中提供了filesystem,提供如下两个api
std::filesystem::remove
std::filesystem::remove_all
其中remove_all可以删除非空目录