每个用户独立专属文件夹
windows 环境下运行,能真正实现文件管理
#include <iostream>
#include <string>
#include<vector>
#include<unordered_map>
#include<fstream>
using namespace std;
// 磁盘大小
const static int BLOCK_SIZE = 512;
// 磁盘数目
const static int BLOCK_NUM = 64;
// 最多用户数
const static int MAX_USER_SIZE = 10;
// 用户是否登录
bool userStatus=false;
// 系统是否处于使用状态
bool exitStatus = false;
class User{
public:
string username="";
string password="";
// 根目录的位置
int rootDir=0;
};
// 注册的用户(账号,密码)
unordered_map<string, User> users;
// 目录文件
class FD {
public:
// 文件还是目录
// 1表示文件,0表示目录
int sta=1;
// 拥有的文件的位置或者下级目录的位置
vector<int> next;
// 地址
int addr=0;
// 归属用户
string username="";
// 使用虚函数,方便父类指针通过方法访问子类属性
virtual string getName() { return ""; }
virtual void setName(string name) { }
virtual string getMessage() { return ""; }
virtual void setMessage(string mess) {}
virtual void setLen(int len) { }
virtual int getLen() { return 0; }
virtual void setFileSta(bool flag) { }
virtual bool getFileSta() { return false; }
virtual int getProCode() { return 7; }
virtual void setProCode(int code) {}
};
// 文件
class File :public FD {
public:
// 文件名
string fileName="";
// 长度
int len=0;
// 保护码
//-----------------------
//1读1 2写10 4删除100 3读写011 5删读101 6删写110 7删除读写111
//-----------------------
int protectCode = 7;
// 数据
string message="";
// 文件是否处于打开状态
bool fileSta=false;
virtual string getName() {return this->fileName; }
virtual void setName(string name) { this->fileName = name; }
virtual string getMessage() { return this->message; }
virtual void setMessage(string mess) { this->message =this->message+mess; this->len = this->message.length(); }
virtual int getProCode() { return this->protectCode; }
virtual void setProCode(int code) { this->protectCode = code; }
virtual void setLen(int len) { this->len = len; }
virtual int getLen() { return this->len; }
virtual void setFileSta(bool flag) { this->fileSta = flag; }
virtual bool getFileSta() { return this->fileSta; }
};
// 目录
class Directory :public FD
{
public:
// 目录名
string dirName;
virtual string getName() {return this->dirName;}
virtual void setName(string name) { this->dirName = name; }
};
// 采用集合的方式存放
FD* block[BLOCK_NUM * BLOCK_SIZE]{};
// 磁盘指针
int blockDic = 0;
// 当前所在路径
vector<int>path;
// 当前账号
// 当前账号
User user;
// 选择函数
void choice();
// 清屏
void cls();
//判断是否有空闲的空间
int findAvaliable();
// 目录操作
// 创建目录
void mkdir(string name);
// 进入目录
void cd(string name);
// 查看当前目录
void dir();
// 删除目录
void rmdir(string name);
// 文件操作
//创建文件
void create(string name);
// 打开文件
void open(string name);
// 读文件
void read(string name);
//写文件
void write(string name);
// 关闭文件
void close(string name);
// 删除文件
void del(string name);
// 设置文件保护码
void set(string name ,int protectedCode);
// 获取用户的数据
void getUserInfomation();
// 存放用户和文件 / 目录的数据
void saveInformation();
//TODO 获取文件和目录的数据
void getFDInformation();
// 获得文件的数据
void getFileData(string name);
// 用户注册
void regis();
// 用户登录
void login();
//主程序
int main()
{
// 测试方便,先添加一个用户
//user.username = "root";
//user.password = "1";
//users["root"]= user;
//Directory *d=new Directory();
//d->dirName = user.username;
//d->sta = 0;
//d->addr = blockDic;
//d->username =user.username;
//block[blockDic++] = d;
实际操作
//string op = "md " + user.username;
//system(op.data());
// 获取用户的数据
getUserInfomation();
// 获取文件和目录的数据
getFDInformation();
//cout << "=========================================" << endl;
//cout << " 欢迎使用文件管理系统:" << endl;
//cout << "功能 指令" << endl;
用户操作
//cout << "注册 register"<<endl;
//cout << "登录 login"<<endl;
//cout << "退出系统 exit" << endl;
目录操作
//cout << "创建目录 mkdir 目录名" << endl;
//cout << "进入目录 cd 目录名" << endl;
//cout << "删除目录 rmdir 目录名" << endl;
//cout << "显示目录 dir " << endl;
文件操作
//cout << "创建文件 create 文件名" << endl;
//cout << "打开文件 open 文件名" << endl;
//cout << "读文件 read 文件名" << endl;
//cout << "写文件 write 文件名" << endl;
//cout << "关闭文件 close " << endl;
//cout << "删除文件 delete 文件名" << endl;
//cout << "修改/设置文件保护码 set 文件名 保护码" << endl;
//cout << "=========================================" <<endl;
//使用状态
while (!exitStatus)
{
cout << "=========================================" << endl;
cout << " 欢迎使用文件管理系统:" << endl;
cout << "功能 指令" << endl;
// 用户操作
cout << "注册 register" << endl;
cout << "登录 login" << endl;
cout << "退出系统 exit" << endl;
// 目录操作
cout << "创建目录 mkdir 目录名" << endl;
cout << "进入目录 cd 目录名" << endl;
cout << "删除目录 rmdir 目录名" << endl;
cout << "显示目录 dir " << endl;
// 文件操作
cout << "创建文件 create 文件名" << endl;
cout << "打开文件 open 文件名" << endl;
cout << "读文件 read 文件名" << endl;
cout << "写文件 write 文件名" << endl;
cout << "关闭文件 close " << endl;
cout << "删除文件 delete 文件名" << endl;
cout << "修改/设置文件保护码 set 文件名 保护码" << endl;
cout << "=========================================" << endl;
// 调用选择函数
choice();
}
// 存放用户和文件/目录的数据
saveInformation();
// 释放资源
for (int i = 0; i < BLOCK_NUM * BLOCK_SIZE; i++) {
if (block[i] != NULL) {
delete block[i];
}
}
return 0;
}
///
// 选择
void choice() {
if (!userStatus) {
cout << "输入指令:";
}
// 登录状态
else {
string p=user.username+"@";
if (path.size() == 1) {
p += "~";
}
else {
for (int i = 1; i < path.size(); i++) {
p += block[path[i]]->getName();
if (i < path.size() - 1) {
p += "/";
}
}
}
p += ">";
cout << p;
}
string keyWord;
cin >> keyWord;
// 指令执行================
// 系统退出
if (keyWord == "exit") {
// 用户变为退出状态
userStatus = false;
// 退出系统
exitStatus = true;
cout << "欢迎下次使用" << endl;
return;
}
// 用户未登录可执行以下指令: 注册和登录
if (!userStatus) {
// 注册用户
if (keyWord == "register") {
regis();
cls();
return;
}
// 用户登录
else if (keyWord == "login") {
login();
cls();
return;
}
else {
cout << "用户状态和指令不匹配或指令不存在" << endl;
cls();
return;
}
}
// 用户必须处于登录状态才能进行以下的操作
if (userStatus) {
// 创建
if (keyWord == "mkdir") {
string dirName;
cin >> dirName;
mkdir(dirName);
cls();
}
else if (keyWord == "cd") {
string dirName;
cin >> dirName;
cd(dirName);
cls();
}
else if (keyWord == "dir") {
dir();
cls();
}
else if (keyWord == "rmdir") {
string name;
cin >> name;
rmdir(name);
cls();
}
else if (keyWord == "create") {
string name;
cin >> name;
create(name);
cls();
}
else if (keyWord == "open") {
string name;
cin >> name;
open(name);
cls();
}
else if (keyWord == "write") {
string name;
cin >> name;
write(name);
cls();
}
else if (keyWord == "read") {
string name;
cin >> name;
read(name);
cls();
}
else if (keyWord == "close") {
string name;
cin >> name;
close(name);
cls();
}
else if (keyWord == "delete") {
string name;
cin >> name;
del(name);
cls();
}
else if (keyWord == "set") {
string name;
cin >> name;
int code;
cin >> code;
set(name,code);
cls();
}
else {
cout << "用户状态和指令不匹配或指令不存在" << endl;
cls();
return;
}
}
}
// 用户注册
void regis() {
if (users.size() == MAX_USER_SIZE) {
cout << "用户已满,不可再注册" << endl;
return;
}
string username;
string password;
string confirmPassword;
cout << "输入账号:";
cin >> username;
cout << "输入密码:";
cin >> password;
cout << "再次输入密码:";
cin >> confirmPassword;
if (username == " " || username == "") {
cout << "账号不能为空" << endl;
return;
}
if (users.count(username) != 0) {
cout << "此账号已存在" << endl;
return;
}
if (password == " " || password == "") {
cout << "密码不能为空" << endl;
return;
}
if (password != confirmPassword) {
cout << "2次密码不一致" << endl;
return;
}
int j = findAvaliable();
if (j == -1) {
cout << "空间已满,无法创建用户" << endl;
return;
}
Directory* root = new Directory();
root->addr = j;
root->dirName = username;
root->sta = 0;
root->username = username;
block[j] = root;
// 实际操作
string op = "md " +username;
system(op.data());
user.username = username;
user.password = password;
user.rootDir = j;
blockDic = ++j;
users[username] = user;
cout << "用户注册成功" << endl;
return;
}
// 用户登录
void login() {
string username;
string password;
cout << "输入账号:";
cin >> username;
cout << "输入密码:";
cin >> password;
if (users.count(username) == 0) {
cout << "账号不存在" << endl;
return;
}
if (users[username].password != password) {
cout << "密码不正确" << endl;
return;
}
else {
userStatus = true;
cout << "用户登录成功" << endl;
user = users[username];
// 获取数据的根目录的位置
path.push_back(user.rootDir);
for (int i = 0; i < path.size(); i++) {
cout << path[i] << " " ;
}
cout<< endl;
}
}
// 清屏
void cls() {
system("pause");
system("cls");
}
//判断是否有空闲的空间
int findAvaliable() {
// 有空闲,则返回位置
int j= blockDic;
for (int i = 0; i < BLOCK_NUM * BLOCK_SIZE; i++) {
if (j == BLOCK_NUM * BLOCK_SIZE) {
j = 0;
}
if (block[j]==NULL) {
return j;
}
j++;
}
// -1 表示没有
return -1;
}
// 目录操作
// 创建目录
void mkdir(string name) {
// 判断是否有空闲的空间
blockDic = findAvaliable();
if (blockDic == -1) {
cout << "磁盘已满" << endl;
return;
}
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
// 判断是否有子目录与name相同
if (block[j]->getName() == name&&block[j]->sta==0) {
cout << "该目录已存在" << endl;
return;
}
}
// 创建目录
Directory *d=new Directory();
d->dirName = name;
d->addr = blockDic;
// 标记为目录
d->sta = 0;
// 设置归属者
d->username = user.username;
// 保存子目录的位置
block[cur_dir]->next.push_back(blockDic);
block[blockDic] = d;
blockDic++;
// 实际操作
//拼路径
string op = "md ";
for (int i = 0; i < path.size(); i++) {
op += block[path[i]]->getName();
op += "\\";
}
op += name;
system(op.data());
}
// 进入目录
void cd(string name) {
// 只能退出到根路径
if (path.size() > 1&& name == "../") {
// 路径回退
path.pop_back();
return;
}
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
// 判断是否有此子目录
for (int i = 0; i < children.size(); i++) {
if (block[children[i]]->getName() == name&& block[children[i]]->sta==0) {
int proCode = block[children[i]]->getProCode();
// 如果没有读权限
if (((proCode & 1) == 0)) {
cout << "没有读权限" << endl;
return;
}
// 进入目录成功
path.push_back(children[i]);
return;
}
}
cout << "没有此目录" << endl;
}
// 查看当前目录
void dir() {
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
if (children.size() == 0) {
cout << "该目录为空" << endl;
return;
}
cout << "文件类型 " << "文件名 " << "物理地址 " << "保护码 " << "文件长度 " << endl;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
cout << (block[j]->sta == 0 ? "目录\t " : "文件\t ") << block[j]->getName() << "\t" << j << "\t "
<< block[j]->getProCode() << "\t" << block[j]->getLen() << endl;
}
}
// 删除目录
void rmdir(string name) {
int cur_dir = path[path.size() - 1];
// 有权限
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
if (block[j]->getName() == name && block[j]->sta == 0) {
// 如果没有删除权限
if ( (((block[j]->getProCode() >> 2) & 1) == 0)) {
cout << "没有删除权限" << endl;
return;
}
// 该目录下还有文件,不允许删除
if (block[j]->next.size() != 0) {
cout << "该目录下还有文件,不允许删除" << endl;
return;
}
if (i != children.size() - 1) {
children[i] ^= children[children.size() - 1];
children[children.size() - 1] ^= children[i];
children[i] ^= children[children.size() - 1];
}
children.pop_back();
block[cur_dir]->next = children;
//可以删除
FD* fd = block[j];
block[j] = NULL;
// 释放资源
delete fd;
cout << "删除成功" << endl;
// 实际操作
string op = "rd ";
for (int i = 0; i < path.size(); i++) {
op += block[path[i]]->getName();
op += "\\";
}
op += name;
system(op.data());
return;
}
}
cout << "查无此目录" << endl;
}
// 文件操作
//创建文件
void create(string name) {
// 判断是否有空闲的空间
blockDic = findAvaliable();
if (blockDic == -1) {
cout << "磁盘已满" << endl;
return;
}
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
// 判断是否有文件名与name相同
if (block[j]->getName() == name && block[j]->sta == 1) {
cout << "该文件已存在" << endl;
return;
}
}
// 创建文件
File* f = new File();
f->fileName = name;
// 标记为文件
f->sta = 1;
// 设置归属者
f->username = user.username;
// 保存文件的位置
f->addr = blockDic;
block[cur_dir]->next.push_back(blockDic);
block[blockDic] = f;
blockDic++;
cout << "文件创建成功" << endl;
//实际操作
string op = "cd.> ";
for (int i = 0; i < path.size(); i++) {
op += block[path[i]]->getName();
op += "\\";
}
op += name+".txt";
system(op.data());
}
// 打开文件
void open(string name) {
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
// 判断是否有文件名与name相同
if (block[j]->getName() == name && block[j]->sta == 1) {
block[j]->setFileSta(true);
cout << name << "文件打开成功" << endl;
// 为了提高效率,打开文件的时候,再将数据读入
if (block[j]->getMessage() == "") {
getFileData(name);
}
return;
}
}
cout << "打开失败:文件不存在" << endl;
}
// 读文件
void read(string name) {
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
// 判断是否有文件名与name相同
if (block[j]->getName() == name && block[j]->sta == 1) {
if (block[j]->getFileSta() == false) {
cout << "文件未打开" << endl;
return;
}
if ( (block[j]->getProCode() & 1) == 0) {
cout << "没有读权限" << endl;
return;
}
cout << name << "文件内容: "<<block[j]->getMessage() << endl;
return;
}
}
}
//写文件
void write(string name) {
// 当前路径
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
// 判断是否有文件名与name相同
if (block[j]->getName() == name && block[j]->sta == 1) {
if (block[j]->getFileSta() == false) {
cout << "文件未打开" << endl;
return;
}
if ((((block[j]->getProCode() >> 1) & 1) == 0)) {
cout << "没有写权限" << endl;
return;
}
cout << name << "文件内容: " << block[j]->getMessage() << endl;
cout << "请输入你想追加的内容:";
string mess;
cin >> mess;
block[j]->setMessage(mess);
cout << "写入成功" << endl;
//实际操作
string op = "echo "+mess+">>";
for (int i = 0; i < path.size(); i++) {
op += block[path[i]]->getName();
op += "/";
}
op += name + ".txt";
system(op.data());
return;
}
}
}
// 关闭文件
void close(string name) {
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
// 判断是否有文件名与name相同
if (block[j]->getName() == name && block[j]->sta == 1) {
if (block[j]->getFileSta() == false) {
cout << "文件已关闭" << endl;
return;
}
block[j]->setFileSta(false);
cout << name << "文件关闭成功" << endl;
return;
}
}
cout << "关闭失败:文件不存在" << endl;
}
// 删除文件
void del(string name) {
int cur_dir = path[path.size() - 1];
// 有权限
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
// 如果没有写权限
if ( (((block[j]->getProCode() >> 2) & 1 )== 0)) {
cout << "没有删除权限" << endl;
return;
}
// 判断是否有文件名与name相同
if (block[j]->getName() == name && block[j]->sta == 1) {
// 判断文件是否被打开
if (block[j]->getFileSta() == true) {
cout << "文件被打开,不可删除!!!" << endl;
return;
}
// 和最后一位的位置数据交换,然后弹出最后一位数据
if (i != children.size() - 1) {
children[i] ^= children[children.size() - 1];
children[children.size() - 1] ^= children[i];
children[i] ^= children[children.size() - 1];
}
children.pop_back();
block[cur_dir]->next = children;
// 删除
FD* fd = block[j];
block[j] = NULL;
delete fd;
cout << "文件删除成功" << endl;
//实际操作
string op = "del ";
for (int i = 0; i < path.size(); i++) {
op += block[path[i]]->getName();
op += "\\";
}
op += name + ".txt";
system(op.data());
return;
}
}
cout << "查无此文件" << endl;
}
// 设置文件保护码
void set(string name, int protectedCode) {
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
// 判断是否有此文件
if (block[children[i]]->getName() == name) {
// 判断是否是文件的拥有者,是才有设置保护码的权限
if (user.username != block[children[i]]->username) {
cout << "无权修改保护码" << endl;
return;
}
block[children[i]]->setProCode( protectedCode);
cout << "修改成功" << endl;
}
}
}
// 获取用户的数据
void getUserInfomation() {
ifstream ifs;
ifs.open("user.txt", ios::in);
if (!ifs.is_open()) //打开失败
{
}
else {
while (!ifs.eof()) {
User u;
string a;
ifs >> u.username >> u.password >> a;
// 获取数据
if (u.username != "" && u.username != " ") {
u.rootDir =a[0]- '0';
users[u.username] = u;
}
}
}
ifs.close();
}
// 存放用户和文件 / 目录的数据
void saveInformation() {
// 是否成功打开
bool flag = true;
string s = "del user.txt";
ifstream ifs;
ifs.open("user.txt", ios::in);
if (!ifs.is_open()) //打开失败
{
flag = false;
}
ifs.close();
// 文件存在
if (flag) { system(s.data()); }
flag = true;
s = "del data.txt";
ifstream is;
is.open("data.txt", ios::in);
if (!is.is_open()) //打开失败
{
flag = false;
}
is.close();
// 文件存在
if(flag) { system(s.data()); }
// 存放用户的数据
ofstream os;
os.open("user.txt", ios::out|ios::app);
for (auto i = users.cbegin(); i != users.cend();i++) {
User u = i->second;
os<< u.username << " " << u.password << " " << u.rootDir<<" " << endl;
}
os.close();
// 存放文件和目录的数据
ofstream ofs;
ofs.open("data.txt", ios::out | ios::app);
for (int i = 0; i < BLOCK_NUM * BLOCK_SIZE; i++) {
if (block[i] != NULL) {
// 文件
if (block[i]->sta == 1) {
ofs << block[i]->sta << " " << block[i]->addr << " "
<< block[i]->username<<" "<< block[i]->getName()<<" "
<< block[i]->getLen()<<" "<< block[i]->getProCode();
ofs << endl;
}
// 目录
if (block[i]->sta ==0) {
ofs << block[i]->sta << " " << block[i]->addr << " "
<< block[i]->username << " " << block[i]->getName();
// 存放子目录和文件的位置
vector<int> children = block[i]->next;
for (int i = 0; i < children.size(); i++) {
ofs << " " << children[i];
}
ofs << endl;
}
}
}
ofs.close();
}
// 获取文件和目录的数据
void getFDInformation() {
ifstream ifs;
ifs.open("data.txt", ios::in);
if (!ifs.is_open()) //打开失败
{}
else {
while (!ifs.eof()) {
string s;
getline(ifs, s);
if (s == "" || s == " ")break;
int type = s.at(0) - '0';
string tmpStr = "";
vector<string> data;
for (int i = 0; i < s.size(); i++) {
if (s[i] != ' ') {
tmpStr += s[i];
}
if (tmpStr != "" && i == s.size() - 1) {
data.push_back(tmpStr);
tmpStr = "";
}
if (s[i + 1] == ' ' && tmpStr != "") {
data.push_back(tmpStr);
tmpStr = "";
}
}
FD* fd{};
// 目录
if (type == 0) {
fd = new Directory();
}
// 文件
else if (type == 1) {
fd = new File();
}
if (fd != NULL) {
for (int i = 0; i < data.size(); i++) {
// 目录
if (type == 0) {
// 将sta解析出来
if (i == 0) {
int n = 0;
// 第一个数据转化成int
n = data[i][0] - '0';
fd->sta = n;
}
// 解析地址
else if (i == 1) {
int n = 0, mul = 1;
// 第二个数据转化成int
for (int j = data[i].length() - 1; j >= 0; j--) {
n += ((data[i][j] - '0') * mul);
mul *= 10;
}
fd->addr = n;
}
// 解析username
else if (i == 2) {
fd->username = data[i];
}
// 解析dirName
else if (i == 3) {
fd->setName(data[i]);
}
else {
int n = 0, mul = 1;
for (int j = data[i].length() - 1; j >= 0; j--) {
n += ((data[i][j] - '0') * mul);
mul *= 10;
}
fd->next.push_back(n);
}
}
// 文件
else if (type == 1) {
// 将sta解析出来
if (i == 0) {
int n = 0;
// 第一个数据转化成int
n = data[i][0] - '0';
fd->sta = n;
}
// 解析地址
else if (i == 1) {
int n = 0, mul = 1;
// 第二个数据转化成int
for (int j = data[i].length() - 1; j >= 0; j--) {
n += ((data[i][j] - '0') * mul);
mul *= 10;
}
fd->addr = n;
}
// 解析username
else if (i == 2) {
fd->username = data[i];
}
// 解析dirName
else if (i == 3) {
fd->setName(data[i]);
}
// 解析len
else if (i == 4) {
int n = 0, mul = 1;
for (int j = data[i].length() - 1; j >= 0; j--) {
n += ((data[i][j] - '0') * mul);
mul *= 10;
}
fd->setLen(n);
}
// 解析protectedCode
else if (i == 5) {
int n = 0;
n = data[i][0] - '0';
fd->setProCode(n);
}
}
}
// 将数据放入磁盘
block[fd->addr] = fd;
data.clear();
}
}
}
ifs.close();
}
// 获得文件的数据
void getFileData(string name) {
string op = "";
for (int i = 0; i < path.size(); i++) {
op += block[path[i]]->getName();
op += "/";
}
op +=( name + ".txt");
ifstream ifs;
ifs.open(op, ios::in);
if (!ifs.is_open()) //打开失败
{
}
else {
string data;
while (!ifs.eof()) {
string s;
ifs >> s;
data += s;
}
// 当前路径
int cur_dir = path[path.size() - 1];
vector<int>children = block[cur_dir]->next;
for (int i = 0; i < children.size(); i++) {
int j = children[i];
// 判断是否有文件名与name相同
if (block[j]->getName() == name) {
block[j]->setMessage(data);
break;
}
}
}
ifs.close();
}