C/C++模拟操作系统文件操作

来源:互联网 发布:开票软件怎么用 编辑:程序博客网 时间:2024/06/16 22:01

效果图

这里写图片描述

基本要求

利用磁盘文件实现操作系统的文件管理功能,主要包括目录结构的管理、外存空间的分配与释放以及空闲空间管理三部分。

实验提示

  1. 通过初始化操作建立一个模拟外存空间的虚拟磁盘文件,在该文件中保存目录和文件内容。创建该文件时应创建初始的根目录内容、文件分配表。根目录实为一特殊文件,其开始内容为空,大小为一个块。
  2. 文件目录项(可以采用FCB格式)应包括类型(目录 or文件)、创建日期、大小、第一个磁盘块块号。
  3. 显示命令提示符“$”,并根据输入命令完成相应的文件操作:
    • MD(创建子目录):创建目录文件,并在父目录文件中增加目录项。
    • CD(切换工作目录):根据当前目录切换到指定目录。
    • RD(删除子目录):搜索所要删除的目录是否为空目录,若是则删除。
    • MK(创建空文件):创建指定大小的文件(如输入命令 “mk test 2000”,表示创建大小为2000字节的test文件),并在父目录中添加文件名称;还应对FAT表进行适当修改。
    • DIR:列出当前目录的所有目录项。
    • FORMAT:根据进一步的虚拟磁盘文件名和块个数信息创建出虚拟磁盘文件。

代码

首先是基本DOS命令函数头文件.< < DOS.h > >

#ifndef DOS_H_INCLUDED#define DOS_H_INCLUDED#include <iostream>#include <fstream>#include <string>#include <algorithm>#include <ctime>#include <cstdlib>#include <cmath>#define LAST_BLOCK 0xFFFF//fat16#define EMPTY_BLOCK 0x0000#define BLOCK_SIZE 1024#define BEEP 7using namespace std;typedef struct FCB{    char name[8];//文件或者目录名    int size;//文件或者目录字节数    int first_block;//第一个块号    char dateTime[15];//日期时间    char type;//1.文件 2.目录 0.空闲}FCB;string current_directory = "";string format_file_name = "";int current_directory_block_no = 0;//当前目录块号namespace DOS {    void alert(char str[]) {        cout<<str<<endl;    }    bool is_all_digits(string &str) {//判断是否为全数字        for(int i = 0; i < str.length(); i++) {            if(str[i] < '0' || str[i] > '9') {                return false;            }        }        return true;    }    int to_integer (string &str) {//字符串转化为数字        if(is_all_digits(str)) {            return atoi(str.c_str());        }        return -1;    }    bool is_power_of_two(int i) {//判断是否为2的整数次幂        if(i % 2 != 0) {            return false;        } else {            while(i != 1) {                if(i%2 != 0) {                    return false;                }                i = i/2;            }        }        return true;    }    void trim (char *str) {//去掉前后空格        char *p = str;        while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {            p++;        }        strcmp(str, p);        int i = strlen(str)-1;        while(str[i] == ' ' || str[i] == '\t' || str[i] == '\r' || str[i] == '\n') {            i--;        }        str[i+1] = '\0';    }    void toUpperCase (string &str) {        transform(str.begin(), str.end(), str.begin(), ::toupper);    }    void toLowerCase (string &str) {        transform(str.begin(), str.end(), str.begin(), ::tolower);    }    int split (string &str,string ss[10],char ch) {//分割字符串        int i = 0, j = 0, k = 0;        while(str[i] == ch) {            i++;        }//       if(str[i] == 0) {//           return 0;//      }        char a[10][40];        int index = 0;        for(;i < str.length(); i++) {            if(str[i] != ch) {                a[j][k++] = str[i];            }else {                a[j][k] = '\0';                if(k != 0) {                   ss[index] = a[j];                   index++;                }                j++;                k = 0;            }        }        a[j][k] = '\0';        if(k != 0) {            ss[index] = a[j];            index++;        }        return index;    }    void setDateTime(char dateTime[]) {        time_t ticks = time(NULL);        struct tm *t = localtime(&ticks);        strftime(dateTime, 16, "%Y%m%d %H%M%S", t);    }    int get_block_count() {//获取块大小        ifstream in (format_file_name.c_str(), ios::in|ios::binary|ios::ate);        long size = in.tellg();        in.close();        return size/(BLOCK_SIZE+2);    }    int get_file_size(string &str) {//获取文件大小        ifstream in (str.c_str(), ios::in|ios::binary|ios::ate);        long size = in.tellg();        in.close();        return size;    }    void read_fat(char *c) {        ifstream in (format_file_name.c_str(), ios::in|ios::binary);        if(!in.is_open()) {            alert("Failed to create file!!");            return;        }        int length = get_block_count();        in.read(c, 2*length);        in.close();    }    void write_fat(char *c) {        FILE *fp = fopen(format_file_name.c_str(), "rb+");        if(fp == NULL) return;        fwrite( c, 2*get_block_count(), 1, fp);        fclose(fp);    }    void read_block(int block_no, char *str) {        ifstream in (format_file_name.c_str(), ios::in|ios::binary);        if(!in.is_open()) {            alert("Failed to create file!!");            return;        }        in.seekg((get_block_count()*2 + block_no*BLOCK_SIZE),ios::beg);        in.read(str, BLOCK_SIZE);        in.close();    }    void write_block(int block_no, char *str) {        FILE *fp = fopen(format_file_name.c_str(), "rb+");        if(fp == NULL) {            return;        }        int i = get_block_count()*2 + block_no*BLOCK_SIZE;        fseek(fp, i, 0);        fwrite(str, BLOCK_SIZE,1,fp);        fclose(fp);    }    int get_empty_block_num(int start) {//start开始以后后面第一个空闲块号        char *fat;        unsigned short *tmp;        int blockNum = -1;        int i, length;        length = get_block_count();        fat = new char [get_block_count()*2];        read_fat(fat);        tmp = (unsigned short*)fat;        for(i = 0; i < start; i++, tmp++);        for(; i < length; i++, tmp++) {            //cout<<(short *)*tmp<<endl;            if( *tmp == EMPTY_BLOCK) {                blockNum = i;                break;            }        }        delete[] fat;        //cout<<blockNum<<endl;        return blockNum;    }    void set_fat_item(int idx, unsigned short c) {//设置FAT表第idx项为c        char *fat, *tmp;        unsigned short *shortPnt;        fat = new char [get_block_count()*2];        read_fat(fat);        shortPnt=(unsigned short*)fat;        *(shortPnt+idx) = c;        //printf("%4x%d",c,idx);        write_fat(fat);        delete[] fat;    }    char get_fat_item(int idx) {        char *fat, *tmp;        fat = new char [get_block_count()*2];        read_fat(fat);        char c = *(fat+idx);        delete[] fat;        return c;    }    bool is_valid_name (string &str) {//判断文件名是否符合规矩        if(str.find("\\", 0) != -1) {            alert("The file or directory name includes illegal characters");            return false;        }else if(str.length() > 8) {            alert("The file or directory name can not exceed 8 characters");            return false;        }else if(str == "." || str == "..") {            alert("The file or directory name can not make '.' Or '..'");            return false;        }        return true;    }    void display_vd_content(int pos, int length) {//显示内容核心        ifstream in(format_file_name.c_str(), ios::binary|ios::in);        if(!in.is_open()) {            alert("Failed to open file!!");            return;        }        in.seekg(pos, ios::beg);        int  i = 0;        char c;        while(i < length) {            printf("%08d  ", pos+i);            for(int j = 0; j < 16; j++) {                char tmp[20];                in.read(&c, 1);                if(in.eof()) {                    break;                }                sprintf(tmp, "%02x", c);                if(strlen(tmp) > 2) {                    string tmm = tmp;                    cout<<tmm.substr(strlen(tmp)-2, 2)<<" ";                }else {                    printf("%02x ",c);                }                            i++;            }            in.seekg(-16, ios::cur);            cout<<"  ";            for(int j = 0; j < 16; j++) {                in.read(&c, 1);                if(in.eof()) {                    break;                }                if(c > 13  &&  c < 127) {                    cout<<c;                }else {                    cout<<".";                }            }            cout<<endl;        }        in.close();    }    void display_content(string &str1, string &str2) {//显示内容        int start = to_integer(str1);        if(start >= 0) {            int length = to_integer(str2);            if(length > 0) {                display_vd_content(start, length);            }else {                display_vd_content(start, 256);            }        }else {        }    }    void display_content(string &str1) {        toLowerCase(str1);        if(str1 == "fat") {            ifstream in (format_file_name.c_str(), ios::in|ios::binary|ios::ate);            long size = in.tellg();            in.close();            display_vd_content(0, (size/(BLOCK_SIZE+2))*2 );        }    }    void write_directory_content(int block_no, int parent_block_no, char *dateTime) {        char *directory_content = new char[BLOCK_SIZE];        memset(directory_content, 0, BLOCK_SIZE);        FCB *tmp = (FCB *)directory_content;        strcpy(tmp->name , ".");        strcpy(tmp->dateTime, dateTime);        tmp->size = BLOCK_SIZE;        tmp->first_block = block_no;        tmp->type = 2;        tmp++;        strcpy(tmp->name , "..");        strcpy(tmp->dateTime, dateTime);        tmp->size = BLOCK_SIZE;        tmp->first_block = parent_block_no;        tmp->type = 2;        tmp++;        write_block(block_no, directory_content);        delete []directory_content;    }    void do_format(string &str, int integer, int Bsize) {//创建FAT表文件        if(!is_power_of_two(integer)) {            alert("Not the power of 2");        } else if (integer > 65535) {//64K minus FAT minus 0000            alert("Exceeds the maximum memory range");        } else {            ofstream out(str.c_str(), ios::out|ios::binary);            if(!out.is_open()) {                alert("Failed to create file!!");            } else {                format_file_name = str;                cout<<"Formatting:  "<<str<<", BlockSize:  "<<Bsize<<", BlockNum:  "<<integer<<endl;                int myByte = LAST_BLOCK;                out.write((char*)&myByte, 2);                myByte = EMPTY_BLOCK;                for(int i = 0; i < integer-1; i++) {                    out.write((char*)&myByte, 2);                }                char buf[BLOCK_SIZE];                memset(buf, 0, BLOCK_SIZE);                for(int i = 0; i < integer; i++) {                    out.write(buf, BLOCK_SIZE);                }                char dateTime[15];                setDateTime(dateTime);                write_directory_content(0,0,dateTime);                out.close();            }        }    }    void format(){        string aa = "a";        do_format(aa, 32, BLOCK_SIZE);    }    void help() {    }    FCB* get_directory_item(FCB *content, int type, char *name) {        FCB *tmp = content;        for(int i = 0; i < BLOCK_SIZE/sizeof(FCB); i++, tmp++) {            if(tmp->type == type) {                if(strcmp(tmp->name, name)==0) {                    return tmp;                }            }        }        return NULL;    }    void md(char *name) {//创建目录        string ss = name;        if(!is_valid_name(ss)) {            return;        }        FCB *directory_content = new FCB[BLOCK_SIZE];        read_block(current_directory_block_no, (char *)directory_content);        if(get_directory_item(directory_content, 1, name) != NULL  ||  get_directory_item(directory_content, 2, name) != NULL) {            alert("Directory name is occupied");            delete[] directory_content;            return;        }        int block_no = get_empty_block_num(0);        if(block_no < 0) {            alert("insufficient space in drive");            delete[] directory_content;            return;        }        FCB *tmp = directory_content;        for(int i = 0; i < BLOCK_SIZE/sizeof(FCB); i++, tmp++) {            if(tmp->type == 0) {                char dateTime[15];                setDateTime(dateTime);                strcpy(tmp->name, name);                tmp->size = BLOCK_SIZE;                tmp->first_block = block_no;                strcpy(tmp->dateTime, dateTime);                tmp->type=(char)2;                write_block(current_directory_block_no, (char *)directory_content);                set_fat_item(block_no, LAST_BLOCK);                delete[] directory_content;                write_directory_content(block_no, current_directory_block_no, dateTime);                return;            }        }    }    void rd(string &name) {//删除目录        char aa[100];        strcpy(aa, name.c_str());        if(!is_valid_name(name)) {            return;        }        FCB *directory_content = new FCB[BLOCK_SIZE];        read_block(0, (char *)directory_content);        FCB *tmp, *tmp2;        tmp = directory_content;        tmp2 = get_directory_item(directory_content, 2, aa);        if(tmp2 != NULL) {            char *content = new char [BLOCK_SIZE];            memset(content, 0, BLOCK_SIZE);            int block_no = tmp2->first_block;            cout<<block_no<<endl;            write_block(block_no, content);            set_fat_item(block_no, EMPTY_BLOCK);            memset((char *)tmp2, 0, sizeof(FCB));                write_block(0, (char *)directory_content);                delete[] directory_content;        }else {            cout<<"Not Find Name"<<endl;        }    }    void dir() {//显示目录        FCB *directory_content = new FCB [BLOCK_SIZE];        read_block(current_directory_block_no, (char *)directory_content);        FCB *tmp = directory_content;        for(int i = 0; i < BLOCK_SIZE/sizeof(FCB); i++, tmp++) {            if(tmp->type == 1 || tmp->type == 2) {                int type = tmp->type;                if(tmp->first_block >=0 ) {                    printf("%d\t", tmp->first_block);                }else {                    printf("\t");                }                *(tmp->dateTime+15) = 0;                printf("%s\t", tmp->dateTime);                if(type == 2) {                    printf("<DIR>\t");                }else {                    printf("%d\t", tmp->size);                }                printf("%s\n", tmp->name);            }        }        delete []directory_content;    }    void cd(string &name) {//定位        if(name == "NULL") {            if(current_directory.length() == 0) {                cout<<"\\ "<<endl;            }else {                cout<<current_directory<<endl;            }        }else if(name == ".") {            return;        }else if(name == "\\"){            current_directory_block_no = 0;            current_directory = "";            return;        }else {            FCB *directory_content = new FCB [BLOCK_SIZE];            read_block(current_directory_block_no, (char *)directory_content);            char name1[100];            strcpy(name1, name.c_str());            FCB *tmp = get_directory_item(directory_content, 2, name1);            if(tmp == NULL) {                alert("Not Find Contents");            }else {                current_directory_block_no = tmp->first_block;                current_directory+="\\";                current_directory+=name1;            }            delete []directory_content;        }    }    void mk(char *name, int size, char *content) {//创建文件        string ss = name;        if(!is_valid_name(ss)) {            return;        }        FCB *directory_content = new FCB[BLOCK_SIZE];        read_block(current_directory_block_no, (char *)directory_content);        if(get_directory_item(directory_content, 1, name) != NULL  ||  get_directory_item(directory_content, 2, name) != NULL) {            alert("Directory name is occupied");            delete[] directory_content;            return;        }        int block_no = get_empty_block_num(0);        if(block_no < 0) {            alert("insufficient space in drive");            delete[] directory_content;            return;        }        FCB *tmp = directory_content;        for(int i = 0; i < BLOCK_SIZE/sizeof(FCB); i++, tmp++) {            if(tmp->type == 0) {                char dateTime[15];                setDateTime(dateTime);                strcpy(tmp->name, name);                strcpy(tmp->dateTime, dateTime);                tmp->type=(char)1;                tmp->size = size;                if(size > 0) {                    tmp->first_block = block_no;                    int block_count = (int)ceil(size/(double)BLOCK_SIZE);                    int *block_numbers = new int[sizeof(int)*block_count];                    *block_numbers = block_no;                    for(int j = 1; j < block_count; j++) {                        *(block_numbers+j) = get_empty_block_num(*(block_numbers + j - 1) + 1);                        if(*(block_numbers + j) == -1) {                            alert("There is not enough memory space");                            delete[] block_numbers;                            delete[] directory_content;                            return;                        }                    }                    for(int j = 0; j < block_count; j++) {                        if( (j+1) == block_count) {                            set_fat_item(*(block_numbers + j), LAST_BLOCK);                        }else {                            set_fat_item(*(block_numbers + j), *(block_numbers + j + 1));                        }                        write_block(*(block_numbers+j), (char *)(content+BLOCK_SIZE*j));                    }                    delete[] block_numbers;                }else {                    tmp->first_block = -1;                }                write_block(current_directory_block_no, (char *)directory_content);                delete[] directory_content;                return;            }        }        alert("The parent directory is full");        delete[] directory_content;    }    void del(string &name) {//删除文件    }    void put(string &src, string &dest) {        FILE *fp = fopen(src.c_str(), "rb");        if(fp == NULL) {            alert("Did not find the local file");        }else {            int size = get_file_size(src);            char *content = new char [(int)(ceil(size/(double)BLOCK_SIZE)) * BLOCK_SIZE];            memset(content, 0, ceil(size/(double)BLOCK_SIZE) * BLOCK_SIZE);            fread(content, size, 1, fp);            if(dest == "NULL") {                char aa[100];                strcpy(aa, src.c_str());                mk(aa, size, content);            }else {                char bb[100];                strcpy(bb, dest.c_str());                mk(bb, size, content);            }            delete[] content;        }        fclose(fp);    }}#endif // DOS_H_INCLUDED

主函数文件

#include <iostream>#include <string>#include <cstdlib>#include <ctime>#include "windows.h"#include "FCB.h"#include "DOS.h"//char current_directory[256] = "";//当前目录//char format_file_name[32];//虚拟磁盘文件名using namespace std;using namespace DOS;int main(){        /*char *content = new char [sizeof(FCB)];            memset(content, 0, sizeof(FCB));            cout<<content<<endl;        return 0;*/    while(1) {        string cmd, str[10];        int length;        if(current_directory.length() == 0) {            cout<<"\\$ ";        }else {            cout<<current_directory<<"$ ";        }        getline(cin,cmd);        length = split(cmd, str, ' ');        toLowerCase(str[0]);        if(str[0] == "exit") {            exit(0);        } else if(str[0] == "cls") {            system("cls");        } else if(str[0] == "help" || str[0] == "?") {            help();        } else if(str[0] == "format") {            if(length == 3) {                do_format(str[1], to_integer(str[2]), BLOCK_SIZE);            }else {                format();            }        } else if(str[0] == "info") {            if(length == 2) {                display_content(str[1]);            }else if (length == 3) {                display_content(str[1], str[2]);            }else {                alert("Error command!");            }        } else if(str[0] == "md" && length == 2) {            char aa[100];            strcpy(aa, str[1].c_str());            md(aa);        } else if(str[0] == "dir") {            dir();        } else if(str[0] == "cd"){            //char bb[100];            //strcpy(bb, str[1].c_str());            if(length == 2) {                cd(str[1]);            }else {                string bb = "NULL";                cd(bb);            }        } else if(str[0] == "mk" && length == 2){            char bb[100];            strcpy(bb, str[1].c_str());            mk(bb, 0, NULL);        } else if(str[0] == "mk" && length == 3){            int size = to_integer(str[2]);            if(size > 0) {                char *content = (char *)malloc(size);                memset(content, 0, size);                char cc[100];                strcpy(cc, str[1].c_str());                mk(cc, size, content);            }        } else if(str[0] == "put" && length == 2){            string cc = "NULL";            put(str[1], cc);        } else if(str[0] == "put" && length == 3){            put(str[1], str[2]);        } else if(str[0] == "rd" && length == 2){            rd(str[1]);        } else if(str[0] == "del" && length == 2){        } else {            alert("Error command!");        }    }    return 0;}
1 0
原创粉丝点击