简单文件系统的实现

来源:互联网 发布:linux下perl开发工具 编辑:程序博客网 时间:2024/05/16 07:41

实现一个简单的文件系统,支持一些基本操作,目前的版本非常简陋以及鲁棒性比较差~( ̄0 ̄)/

结构

将文件系统组织成一个目录树,每个节点为目录,节点的属性包括{目录名,当前路径,父节点,子目录们,该目录下的文件}
因此,我们可以定义我们的节点属性:

struct node {    string name;    string pwd;    node *fa;    //save dirs    set<node*> sons;    //save files    set<string> files;}

在OS中,文件是通过文件名索引的, 我们在查找目录的时候,我们是通过目录名称索引目录的,因此,还需要创建一个目录名称到目录节点的索引:

map<string, node*> basic;

操作

ls(列出该目录下的所有目录和文件)

首先,每个文件目录下,都包含“.”和“..”,分别代表当前目录和上一个目录,然后,我们只需要遍历它的子节点(目录们),该目录下的文件即可。从我们之前对目录结构的定义,可以方便的通过遍历set来遍历目录和文件

void ls() {    cout << "Directories: " << endl;    cout << "." << "\t" << ".." << "\t";    for (auto t : sons) {        if (t != fa && t != this) {            cout << t->name << "\t";        }    }    cout << endl;    cout << "Files: " << endl;    for (auto t : files) {        cout << t << "\t";    }       cout << endl;}

cd(跳转的相应目录)

目前版本只支持相对路径的跳转,并且只能单步跳转
首先,“.”和“..”特判一下,然后,我们再去索引相应的目录。这时候,我们在结构体里面设计的basic就有用了。首先,通过basic从目录名称映射到我们的节点,然后,把当前节点的指针cur指向basic映射到的节点即可

if (cmd.substr(0, 2) == "cd") {        string t = cmd.substr(3, cmd.size() - 3);        if (t == ".") {            continue;        }        if (t == "..") {            if (cur == root) continue;            cur = cur->fa;            continue;        }        if (cur->basic.find(t) == cur->basic.end()) {            cout << "No such folder" << endl;        } else {            node *next = cur->basic[t];            cur = next;        }        continue;}

mkdir(在当前目录下新建一个目录)

新建一个节点,并且将当前节点cur的子节点中加入该新节点,创建新的索引,并且更新路径

if (cmd.substr(0, 5) == "mkdir") {    string t = cmd.substr(6, cmd.size() - 6);    node* tmp = new node(cur, t);    cur->basic[t] = tmp;    cur->sons.insert(tmp);    continue;}

rmdir(在当前目录下删除一个目录)

首先,我们在basic里面去查找该目录下有没有我们要删除的目录,如果找到了,我们只需要把它从sons的set里面删掉,并且把索引也删掉即可

if (cmd.substr(0, 5) == "rmdir") {    string t = cmd.substr(6, cmd.size() - 6);    bool flag = false;    for (auto it = cur->basic.begin(); it != cur->basic.end(); it++) {        if (it->first == t) flag = true;    }    if (!flag) {        cout << "No such folder" << endl;        continue;    }    //del map from basic;    for (auto it = cur->basic.begin(); it != cur->basic.end(); it++) {        if (it->first == t) {            cur->basic.erase(it);            break;        }    }    //del node from sons;    for (auto it = cur->sons.begin(); it != cur->sons.end(); it++) {        node *tnode = *it;        if (tnode->name == t) {        cur->sons.erase(it);            break;        }    }    continue;}

touch(新建一个文件)

只需要在当前节点的files的set里面插入该文件名即可

if (cmd.substr(0, 5) == "touch") {    string t = cmd.substr(6, cmd.size() - 6);    if (cur->files.find(t) != cur->files.end()) {        cout << "File already exist" << endl;        continue;    }    cur->files.insert(t);    continue;}

rm(删除一个文件)

通过在files的集合里面查找文件,判断文件是否存在,如果存在,从set里面删除它即可

if (cmd.substr(0, 2) == "rm") {    string t = cmd.substr(3, cmd.size() - 3);    if (cur->files.find(t) == cur->files.end()) {        cout << "No such file" << endl;        continue;    }    for (auto it = cur->files.begin(); it != cur->files.end(); it++) {        if (*it == t) {            cur->files.erase(it);            break;        }    }    continue;}

pwd(获取当前路径)

在每次新建一个子节点的时候,更新子节点的路径

pwd = pa->pwd + s + "/";

代码

最后,我们完整的代码如下:

#include <bits/stdc++.h>using namespace std;struct node {    string name;    string pwd;    node *fa;    //save dirs    set<node*> sons;    //save files    set<string> files;    map<string, node*> basic;    node(string s) {        name = s;        fa = NULL;        files.clear();    }    node(node *pa, string s) {        name = s;        pwd = pa->pwd + s + "/";        fa = pa;        files.clear();    }    void ls() {        cout << "Directories: " << endl;        cout << "." << "\t" << ".." << "\t";        for (auto t : sons) {            if (t != fa && t != this) {                cout << t->name << "\t";            }        }        cout << endl;        cout << "Files: " << endl;        for (auto t : files) {            cout << t << "\t";        }           cout << endl;    }};node* cur;node* root;void init() {    root = new node("/");    root->name = "root";    root->pwd = "/";    root->basic["."] = root;    root->basic[".."] = root;   }int main() {    init();    cur = root;    while (1) {        cout << "lz console: ";        string cmd;        getline(cin, cmd);        if (cmd == "quit") break;        //call cd        if (cmd.substr(0, 2) == "cd") {                string t = cmd.substr(3, cmd.size() - 3);                if (t == ".") {                    continue;                }                if (t == "..") {                    if (cur == root) continue;                    cur = cur->fa;                    continue;                }                if (cur->basic.find(t) == cur->basic.end()) {                    cout << "No such folder" << endl;                } else {                    node *next = cur->basic[t];                    cur = next;                }                continue;        }        //call pwd        if (cmd == "pwd") {            cout << cur->pwd << endl;            continue;        }        //call ls        if (cmd.substr(0, 2) == "ls") {            cout << "Directories: " << endl;            cout << "." << "\t" << ".." << "\t";            for (auto t : cur->sons) {                if (t == cur->fa || t == cur) continue;                cout << t->name << "\t";            }            cout << endl;            cout << "Files: " << endl;            for (auto t : cur->files) {                cout << t << "\t";            }            cout << endl;            continue;        }        //call mkdir        if (cmd.substr(0, 5) == "mkdir") {            string t = cmd.substr(6, cmd.size() - 6);            node* tmp = new node(cur, t);            cur->basic[t] = tmp;            cur->sons.insert(tmp);            continue;        }        //rmdir        if (cmd.substr(0, 5) == "rmdir") {            string t = cmd.substr(6, cmd.size() - 6);            cout<< t << endl;            bool flag = false;            for (auto it = cur->basic.begin(); it != cur->basic.end(); it++) {                if (it->first == t) flag = true;            }            if (!flag) {                cout << "No such folder" << endl;                continue;            }            //del map from basic;            for (auto it = cur->basic.begin(); it != cur->basic.end(); it++) {                if (it->first == t) {                    cur->basic.erase(it);                    break;                }            }            //del node from sons;            for (auto it = cur->sons.begin(); it != cur->sons.end(); it++) {                node *tnode = *it;                if (tnode->name == t) {                    cur->sons.erase(it);                    break;                }            }            continue;        }        //touch file        if (cmd.substr(0, 5) == "touch") {            string t = cmd.substr(6, cmd.size() - 6);            if (cur->files.find(t) != cur->files.end()) {                cout << "File already exist" << endl;                continue;            }            cur->files.insert(t);            continue;        }        //rm file        if (cmd.substr(0, 2) == "rm") {            string t = cmd.substr(3, cmd.size() - 3);            if (cur->files.find(t) == cur->files.end()) {                cout << "No such file" << endl;                continue;            }            for (auto it = cur->files.begin(); it != cur->files.end(); it++) {                if (*it == t) {                    cur->files.erase(it);                    break;                }            }            continue;        }    }    return 0;}
0 0