os课设模拟文件系统

摘要

所有的计算机应用程序都需要存储和检索信息,而长期存储信息有三个基本要求:能够存储大量信息;使用信息的进程终止时,信息仍旧存在;必须能使多个进程并发访问有关信息。在这样的条件下,我们抽象出了一个新的概念——文件来解决这一问题。文件是进程创建的信息逻辑单元。作为一名转专业的学生,本次选择了选题中最难的模拟文件系统,一方面是对这个专业的热爱和想要挑战自己的极限,另一方面是想更深入底层,体会操作系统重要的组成部分即文件系统。

本次课程设计选用的开发环境为Visual Studio 2019,编程语言为C++。之所以使用C++的很大一部分原因在于它的面向对象特性以及指针的运用,作为一门底层语言,C++用来开发操作系统的组件再合适不过。在创建文件与文件之间的关系时采用的数据结构为链表。

编写本次课程设计的代码大致花了两天的时间,第一天整体的代码框架已经编写出来,第二天大部分时间都在调试,最后成果非常显著,测试完全达到了预期的效果。本次实验同时结合了操作系统、面向对象、数据结构等方面的知识,是一个综合型的项目,因此收获颇丰。

代码实现

Filesystem.h

//Filesystem.h
#ifndef FILESYSTEM_H
#define FILESYSTEM_H

#include <iostream>
#include <fstream>
#include <string.h>
#include <string>
#include <iomanip>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#define SIZE 20    //文件名最大长度
#define Fname "filesys.txt"
extern int tot_disk; 

void runFun();

typedef struct MyFile         //文件结构体
{
    char name[SIZE];      //文件名 
    int size;                 //文件大小
    string content;           //文件内容
    string etime;             //文件创建时间
    string attribute;         //文件属性
    struct MyFile* nextFile;  //指向文件列表中下一个文件  
} MyFile;

typedef struct MyDir          //目录结构体
{
    char name[SIZE];          //目录名字
    int size;                 //目录大小
    MyDir* postDir;           //后继目录
    MyDir* preDir;            //前驱目录
    MyFile* filePtr;          //该目录下的文件链表指针
    MyDir* dirPtr;            //该目录下的目录链表指针
} MyDir;

class FileSystem //文件系统类
{
private:
    char password[SIZE];   //用户密码
    char name[SIZE];       //用户名称
    int size;                  //用户所使用空间大小
    MyDir* root;               //根目录
    MyDir* currentDir;         //当前目录
    
public:
    FileSystem(char* n, char* c);
    ~FileSystem();
    void init(); //用于重新进入系统时可读入
    void save(); //将内存中的信息保存到磁盘

    int create(); //用于创建文件
    int newDir();  //用于创建目录

    int dele_file(MyFile* file); //删除文件
    int deleteFile();    //删除文件前的逻辑判断
    int dele_dir(MyDir* d); //删除目录
    int deleteDir();     //删除目录前的逻辑判断

    int read(); //读取文件
    int write(); //写入文件

    int dir(); //显示当前目录内容
    int show_path(MyDir* dir); //显示路径的部分实现
    int showPath(); //显示路径

    int getSize();//获得用户所在目录大小
    int format();//对文件系统进行格式化
    MyDir* getCurrentdir(); //获得当前目录
};

#endif // !FILESYSTEM_H

Filesystem.cpp

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <string>
#include <iomanip>
#include <ctime>
#include <iomanip>
#include "FileSystem.h"
using namespace std;
extern int tot_disk = 10000; //定义虚拟磁盘空闲空间大小

FileSystem::FileSystem(char* n, char* c) //初始化成员变量,并文件中的内容导入内存
{ 
    size = 0;
    currentDir = NULL;
    MyDir* root = new MyDir;
    strcpy(root->name, n);
    strcpy(name, n);
    strcpy(password, c);

    this->root = root;
    currentDir = root;
    currentDir->preDir = NULL;
    currentDir->dirPtr = NULL;
    currentDir->filePtr = NULL;
    currentDir->postDir = NULL;

    
    ifstream fcin;
    fcin.open(Fname, ios::in);
    if (!fcin.is_open())
    {
        fcin.close();
        return;
    }
    if (fcin.eof())
    { 
        fcin.close();
        return;
    }
    init();
}
FileSystem::~FileSystem() 
{
    tot_disk += size;		//归还虚拟磁盘空间
    size = 0;				//空间大小归0
    MyDir* d = root; //保存根目录地址
    MyFile* f = currentDir->filePtr; //获取当前目录首文件地址

    while (f != 0) 
    { //循环直至目录为空
        if (f->nextFile == 0) 
        {
            this->dele_file(f);
            f = 0;
            break;
        }
        while (f->nextFile->nextFile != 0) //定位至该目录下的倒二个文件
            f = f->nextFile;
        this->dele_file(f->nextFile); //删除尾文件逻辑联系
        f->nextFile = 0;    //置空
        f = currentDir->filePtr; //重新获取当前目录首文件地址
    }
    while (d != 0) { //以同样的方式循环释放目录空间
        if (d->postDir == 0) {
            this->dele_dir(d);
            d = 0;
            break;
        }
        while (d->postDir->postDir != 0)
            d = d->postDir;
        this->dele_dir(d->postDir);
        d->postDir = 0;
        d = root;
    }
}

void FileSystem::init()
{
    ifstream fcin;
    fcin.open(Fname, ios::in);

    char p_name[SIZE];    
    int p_size;
    string p_content;
    string p_etime;
    string p_attribute; //将磁盘中的信息读入
    while (fcin >> p_name && fcin >> p_size && fcin >> p_etime && fcin >> p_content && fcin >> p_attribute)
    {
        MyFile* p = NULL;
        p = new MyFile;

        strcpy(p->name, p_name);
        p->size = p_size;
        p->content = p_content;
        p->etime = p_etime;
        p->attribute = p_attribute;

        if (currentDir->filePtr == NULL) {  //若目录下没有文件
            p->nextFile = currentDir->filePtr; //利用头插法将文件插入文件链表
            currentDir->filePtr = p;
        }
        else {   //若目录下有文件
            p->nextFile = currentDir->filePtr;
            //p->size=0;
            currentDir->filePtr = p;
            MyDir* h = currentDir;

            //更改上级目录的大小
            while (h != NULL) {
                h->size += p->size;
                h = h->preDir;
            }

        }
        currentDir->filePtr->size = p_size; //将当前文件大小置0
        tot_disk = tot_disk - p->size; //分配磁盘空间
        size += p->size;
    }
    fcin.close();
}

void FileSystem::save()
{
    ofstream fout;
    fout.open(Fname, ios::out);

    MyFile* f = currentDir->filePtr; //获取当前目录首文件地址
    
    if (f != NULL)
    {
        while (f != NULL) 
        {
            fout << f->name << " " << f->size << " "
                << f->etime << " " << "#" << " " << f->attribute << " " << endl;
            f = f->nextFile;
        }
    }
    fout.close();
}

int FileSystem::format() 
{   //格式化文件系统
    tot_disk += size;		//归还虚拟磁盘空间
    size = 0;				//空间大小归0
    MyFile* f = currentDir->filePtr; //获取当前目录首文件地址

    while (f->nextFile != 0)
    { //循环直至目录为空
        while (f->nextFile->nextFile != 0) //定位至该目录下的倒二个文件
            f = f->nextFile;
        this->dele_file(f->nextFile); //删除尾文件逻辑联系
        f->nextFile = 0;    //置空
        f = currentDir->filePtr; //重新获取当前目录首文件地址
    }
    currentDir->filePtr = currentDir->filePtr->nextFile;

    cout << "格式化成功!" << endl;
    return 1;
}

int FileSystem::newDir() 
{  //创建目录
    MyDir* p, * h;
    p = new MyDir;
    cin >> p->name; //读取目录名

    p->dirPtr = NULL;
    p->size = 0;
    p->filePtr = NULL;
    p->postDir = NULL;
    if (currentDir->dirPtr == NULL)
        h = NULL;
    else
        h = currentDir->dirPtr;

    while (h != NULL) { //目录下有子目录,检查是否命名冲突
        if (strcmp(h->name, p->name) == 0) {
            cout << "目录已存在" << endl;
            return 0;
        }
        h = h->postDir;
    }

    //利用头插法将目录插入文件系统
    p->preDir = currentDir;
    p->postDir = currentDir->dirPtr;
    currentDir->dirPtr = p;

    cout << "创建目录成功!" << endl;
    return 1;
}

int FileSystem::create() //创建文件
{
    MyFile* p = NULL;
    p = new MyFile;

    //获取当前的系统时间作为文件的创建时间
    SYSTEMTIME sys;
    GetLocalTime(&sys);
    string mytime = to_string(sys.wYear) + "/" + to_string(sys.wMonth) + "/" + to_string(sys.wDay) + "-"
        + to_string(sys.wHour) + ":" + to_string(sys.wMinute) + ":" + to_string(sys.wSecond);

    if (p == 0) 
    {
        cout << "文件创建失败";
        return 0;
    }
    cin >> p->name >> p->attribute; //读入文件名和属性
    p->etime = mytime;

    if (currentDir->filePtr == NULL) {  //若目录下没有文件
        p->nextFile = currentDir->filePtr; //利用头插法将文件插入文件链表
        currentDir->filePtr = p;
    }
    else {   //若目录下有文件
        MyFile* q = new MyFile;
        q = currentDir->filePtr;
        while (q != NULL)  //检测当时目录下是否存在同名文件
        {  
            if (strcmp(p->name, q->name) == 0) {
                cout << "文件已存在" << endl;
                return 0;
            }
            q = q->nextFile;
        }

        p->nextFile = currentDir->filePtr;
        //p->size=0;
        currentDir->filePtr = p;
        MyDir* h = currentDir;

        //更改上级目录的大小
        while (h != NULL) {
            h->size += p->size;
            h = h->preDir;
        }

    }
    currentDir->filePtr->size = 0; //将当前文件大小置0
    cout << "文件创建成功!" << endl;
    tot_disk = tot_disk - p->size; //分配磁盘空间
    size += p->size;
    return 1;
}

int FileSystem::dele_file(MyFile* f)  //删除文件逻辑
{
    delete f; //释放文件空间
    f = NULL; //置空
    return 1;
}

int FileSystem::deleteFile() 
{
    char temp[SIZE];

    cin >> temp;//读入要删除的文件名称
    MyFile* f;
    MyFile* pre = NULL;
    f = currentDir->filePtr; //保存当前文件地址

    while (f != NULL) { //遍历目录寻找要删除的文件
        if (!strcmp(f->name, temp))
            break;
        pre = f;
        f = f->nextFile;
    }
    if (f == NULL) {
        cout << "未找到此文件" << endl;
        return 0;
    }
    tot_disk += f->size; //归还磁盘空间
    MyDir* d = currentDir;
    while (d != 0) //修改删除文件后各级目录的大小
    {
        d->size -= f->size;
        d = d->preDir;
    }

    if (f == currentDir->filePtr)//删除的文件是头结点
        currentDir->filePtr = currentDir->filePtr->nextFile;
    else   //删除的文件非头结点
        pre->nextFile = f->nextFile;
    size -= f->size; //总空间大小缩减
    delete f; //释放该文件
    f = NULL;
    cout << "文件删除成功!" << endl;
    return 1;
}
int FileSystem::dele_dir(MyDir* d) //删除目录逻辑
{
    delete d;
    d = NULL;
    return 1;
}

int FileSystem::deleteDir() 
{
    char n[SIZE];

    MyDir* p, * pre = NULL;
    p = root;
    p = currentDir->dirPtr;
    cin >> n; //读取删除的目录名

    //判断是否存在该目录
    while (p != NULL) {
        if (strcmp(p->name, n) == 0)
        {
            pre = p; break;
        }
        p = p->postDir;
    }

    if (p == NULL) {
        cout << "删除失败" << endl;
        return 0;
    }

    tot_disk += p->size; //归还磁盘空间
    if (p == currentDir->dirPtr) //若目录是头目录
        currentDir->dirPtr = currentDir->dirPtr->postDir;
    else
        p->preDir->postDir = p->postDir;

    pre = currentDir;
    while (pre != NULL) //修改删除目录后各级目录空间大小
    {
        pre->size -= p->size;
        pre = pre->preDir;
    }
    size -= p->size; //修改总空间大小
    MyDir* d = p->dirPtr; //获取要删除目录的目录链表
    MyFile* f = p->filePtr; //获取要删除目录下的文件
    if (f != 0) {
        while (p->filePtr->nextFile != NULL)//删除此目录下的文件
        {
            f = p->filePtr;
            while (f->nextFile->nextFile != NULL)//寻找最后一个文件结点
                f = f->nextFile;
            this->dele_file(f->nextFile); //尾删法
            f->nextFile = NULL;
        }
        if (p->filePtr->nextFile == NULL) {
            this->dele_file(p->filePtr);
            p->filePtr = NULL;
        }
    }
    if (d != NULL) { //以同样的方式删除目录
        while (p->dirPtr->postDir != NULL)//删除此目录下的目录
        {
            d = p->dirPtr;
            while (d->postDir->postDir != NULL)//寻找最后一个文件结点
                d = d->postDir;
            this->dele_dir(d->postDir);
            d->postDir = NULL;
        }
        if (p->dirPtr->postDir == NULL) {
            this->dele_dir(p->dirPtr);
            p->dirPtr = NULL;
        }
    }
    delete p, d, f;

    cout << "目录删除成功!" << endl;
    return 1;

}


int FileSystem::read()  //读文件
{
    char n[SIZE];
    cin >> n;
    MyFile* f = currentDir->filePtr;
    while (f != 0) 
    { //遍历文件链表直到找到目录文件
        if (strcmp(f->name, n) == 0) 
        {
            cout << f->content << endl;
            return 1;
        }
        f = f->nextFile;
    }
    cout << "此文件不存在" << endl;
    return 0;
}

int FileSystem::write() 
{
    char n[SIZE];
    string s;
    cin >> n;
    MyFile* f = currentDir->filePtr;

    while (f != 0) 
    {
        if (!strcmp(f->name, n)) 
        {
            if (f->attribute == "r")
            {
                cout << "文件不可写" << endl;
                return 0;
            }
            cin >> s;
            f->content = s;
            f->size = s.length();
            tot_disk -= f->size; //分配磁盘空间
            MyDir* d = currentDir;
            while (d != 0)//修改各个上级目录的大小
            {
                d->size += f->size;
                d = d->preDir;
            }
            cout << "文件写入成功!" << endl;
            size += f->size;
            return 1;
        }
        f = f->nextFile;
    }

    cout << "此文件不存在" << endl;
    return 0;
}

int FileSystem::show_path(MyDir* d)//显示当前路径
{
    cout << root->name << ":$ ";
    return 1;
}
int FileSystem::dir() //显示目录下的文件及其信息
{
    MyDir* d = currentDir->dirPtr;
    MyFile* f = currentDir->filePtr;

    if (d == NULL && f == NULL) 
    {
        cout << "当前路径为空" << endl;
        return 0;
    }
    cout << endl;

    if (f != NULL) 
    {
        cout << "文件名" << "\t" << "长度" << "\t"
            << "创建时间" << "\t" << "\t" << "物理地址" << "\t" << "属性" << "\t" << endl;
        while (f != NULL) {
            cout << f->name << "\t" << f->size << "\t"
                << f->etime << "\t" << f << "\t" << f->attribute << "\t" << endl;
            f = f->nextFile;
        }
    }
    return 1;
}

int FileSystem::showPath()//显示当前路径
{
    show_path(currentDir);
    return 1;
}

int FileSystem::getSize() 
{
    return size;
}

MyDir* FileSystem::getCurrentdir() 
{
    return currentDir;
}

void help() //输入提示
{
    cout << "******************************************************************" << endl;
    cout << "*                                                                *" << endl;
    cout << "*                     The Use of Instruction                     *" << endl;
    cout << "*                                                                *" << endl;
    cout << "******************************************************************" << endl;
    cout << "* 1.create + filename + attribute         创建文件,并给出属性    *" << endl;
    cout << "*                                         r只读,w可读可写       *" << endl;
    cout << "* 2.del    + filename                     删除文件               *" << endl;
    cout << "* 3.read   + filename                     读文件                 *" << endl;
    cout << "* 4.write  + filename                     写文件                 *" << endl;
    cout << "* 5.dir                                   显示文件               *" << endl;
    cout << "* 6.format                                格式化文件系统         *" << endl;
    cout << "* 6.clear                                 清屏                   *" << endl;
    cout << "* 7.exit                                  注销                   *" << endl;
    cout << "******************************************************************" << endl
        << endl;

}

int func(char name[30], char pass[30]) 
{
    FileSystem fs(name, pass);
    //fs.setUser(name, pass);
    while (1) {
        system("CLS");
        help();
        while (1) 
        {
            cout << endl;
            string choice;

            fs.showPath();
            cin >> choice; //获取输入命令并执行对应方法
            if (choice == "create")
                fs.create();
            else if (choice == "del")
                fs.deleteFile();
            else if (choice == "read")
                fs.read();
            else if (choice == "dir")
                fs.dir();
            else if (choice == "write")
                fs.write();
            else if (choice == "format")
                fs.format();
            else if (choice == "clear") 
            {
                system("CLS");
                help();
            }
            else if (choice == "exit") 
            {
                fs.save();
                system("CLS");
                cout << "系统正在注销...."<< endl;
                Sleep(3);
                return 0;
            }
            else if (choice == "help") 
            {
                help();
            }
            else
            {
                cout << "命令错误,请重新输入" << endl;
            }
        }
    }

}

void login(char name[30], char pass[30])
{
    char pass2[SIZE];
    while (true)
    {
        cout << "欢迎登录模拟文件系统" << endl;
        cout << "账户:" << name << endl;
        cout << "密码:";
        cin >> pass2;
        if (strcmp(pass, pass2) == 0)
        {
            cout << "密码正确!" << endl;
            cout << "正在登录..." << endl;
            Sleep(1000);
            break;
        }
        else
            cout << "密码错误,请重试" << endl;
        Sleep(1000);
        system("cls");
    }
}

void runFun() {
    char name[30] = "chensl", pass[30] = "123456";
    login(name, pass);
    system("CLS");
    Sleep(2);
    func(name, pass);
}


main.cpp

#include "filesystem.h"

int main() {
    runFun();
    return 0;
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeSlogan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值