?? newfile.cpp
字號:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#include<iostream.h>
#include<windows.h>
#define BLOCK_SIZE 512 //磁盤塊大小
#define DIR_NUM 64 //最多目錄節點數
#define FILE_NUM 512 //最多文件節點數
#define BLOCK_NUM 1024 //磁盤塊數目
#define BUF_NUM 32 //主存緩沖區數目
const char file_system_name[]="fs.dat"; //磁盤文件名
struct dir_node //目錄節點
{
char space;
SYSTEMTIME ctime; //創建時間
char dir_name[32]; //目錄名
int child_dir[8]; //子目錄索引
int dir_count; //當前子目錄數
int child_file[16]; //子文件索引
int file_count; //當前子文件數
int parent; //父目錄索引
};
struct file_node //文件節點
{
char space;
SYSTEMTIME ctime; //創建時間
char file_name[32]; //文件名
int block[4]; //該文件占有的磁盤塊索引
int block_count; //該文件當前占有的磁盤塊數
int file_length; //文件長度
int parent; //父目錄索引
};
struct buffer_node //主存緩沖區節點
{
int flag; //占用標志
int file_id; //占用該緩沖區節點的文件索引
char buf[BLOCK_SIZE*4]; //緩沖區,存放讀寫文件的數據
int length; //緩沖區大小
int offset; //打開系統后第一次寫該文件的開始位置
};
struct dir_node dir[DIR_NUM+1]; //目錄節點表
struct file_node file[FILE_NUM]; //文件節點表
struct buffer_node buffer[BUF_NUM]; //緩沖區數組
int dir_flag[DIR_NUM]; //各目錄節點占用標志,0表示空閑,1表示被占用
int used_dir; //已用的目錄節點數
int file_flag[FILE_NUM]; //各文件節點的占用標志
int used_file; //已用的文件節點數
int block_flag[BLOCK_NUM]; //磁盤塊的占用標志
int used_block; //已用的磁盤塊數
int al_dir[DIR_NUM]; //目錄節點修改登記表
int al_file[FILE_NUM]; //文件節點修改登記表
int al_dflag[DIR_NUM]; //目錄節點占用標志登記表
int al_fflag[FILE_NUM]; //文件節點占用標志登記表
int al_bflag[BLOCK_NUM]; //磁盤塊占用標志登記表
int open_files[FILE_NUM]; //文件讀寫登記表
int curr; //當前目錄索引
struct dir_node *curr_dir; //當前目錄節點指針
char curr_path[512]; //當前路徑
FILE *fp; //文件指針
int f_count; //用于計算被復制目錄下的文件數目
int d_count; //用于計算被復制目錄下的子目錄數目
int b_count; //用于計算被復制目錄下的文件占用的磁盤塊數目
void create_file_system() //創建文件系統
{
fp=fopen(file_system_name,"wb+"); //以讀寫方式打開,如果存在,則覆蓋原來信息,
if(fp==NULL) //否則創建該文件
{
printf("Create file system error!\n");
exit(1);
}
//申請空間
int total=sizeof(int)*(DIR_NUM+FILE_NUM+BLOCK_NUM+3)+sizeof(struct dir_node)*DIR_NUM+sizeof(struct file_node)*FILE_NUM+BLOCK_SIZE*BLOCK_NUM;
for(long len=0;len<total;len++)
fputc(0,fp);
fseek(fp,0,SEEK_SET); //寫超級塊信息
used_dir=1;
fwrite(&used_dir,sizeof(int),1,fp);
used_file=0;
used_block=0;
fwrite(&used_file,sizeof(int),2,fp);
dir_flag[0]=1;
fwrite(&dir_flag[0],sizeof(int),1,fp); //標志對應目錄節點、文件節點的使用情況
fwrite(&dir_flag[1],sizeof(int),DIR_NUM+FILE_NUM+BLOCK_NUM-1,fp);
strcpy(dir[0].dir_name,"A:"); //寫根目錄信息
dir[0].dir_count=0;
dir[0].file_count=0;
dir[0].parent=-1;
GetLocalTime(&dir[0].ctime); //獲得當前時間
fwrite(&dir[0],sizeof(struct dir_node),1,fp);
for(int i=0;i<DIR_NUM;i++) //將所有標記清零
{
al_dir[i]=0;
al_dflag[i]=0;
dir[i].dir_count=0;
dir[i].file_count=0;
}
for(i=0;i<FILE_NUM;i++)
{
al_file[i]=0;
al_fflag[i]=0;
open_files[i]=0;
}
for(i=0;i<BLOCK_NUM;i++)
al_bflag[i]=0;
for(i=0;i<BUF_NUM;i++)
buffer[i].flag=0;
fflush(fp);
fclose(fp);
}
int search(int parent,char *name,int type,int &index) //搜索目錄或文件,成功則返回該文件或目錄的索引
{ //失敗則返回-1,type用來區分要搜索的是文件還是目錄
struct dir_node *p=&dir[parent]; //0表示目錄,1表示文件,index用來指定找到的文件或
int i,temp; //目錄在父目錄下的位置
if(type==0)
for(i=0;i<p->dir_count;i++)
{
temp=p->child_dir[i];
if(strcmp(name,dir[temp].dir_name)==0)
{
index=i;
return temp;
}
}
else
for(i=0;i<p->file_count;i++)
{
temp=p->child_file[i];
if(strcmp(name,file[temp].file_name)==0)
{
index=i;
return temp;
}
}
return -1;
}
int get_parent(char *name,int &p) //根據輸入的字符串,獲得父目錄及真正的文件
{ //或目錄名,引用參數p用來指定目錄或文件名
char buf[32],*path,*s; //的起始位置
int pos,start=0,index;
path=new char[128];
strcpy(path,name);
s=strrchr(path,'/'); //如果沒有指定路徑,則將當前目錄指定為
if(s==NULL) //父目錄
return curr;
pos=(int)(s-path);
p=pos+1;
if(p==(int)strlen(path))
return -1;
path[p]='\0';
s=strchr(path,'/');
pos=(int)(s-path);
if(strncmp(path,"A:",pos)!=0) //前面沒有跟目錄名,則從當前目錄往下搜索
start=curr;
else
path+=3;
while(start!=-1 && (int)strlen(path)>0) //進行搜索,知道路徑名結束或出現不匹配
{
s=strchr(path,'/');
pos=(int)(s-path);
strncpy(buf,path,pos);
buf[pos]='\0';
start=search(start,buf,0,index);
path+=pos+1;
}
return start;
}
int get_block(int pos) //為文件申請磁盤塊,一次調用申請一塊,成功則返回
{ //磁盤塊索引,失敗返回-1
for(int i=0;i<BLOCK_NUM;i++)
if(block_flag[i]==0)
{ //修改磁盤塊使用情況及文件的控制信息
block_flag[i]=1;
al_bflag[i]++;
used_block++;
int top=file[pos].block_count;
file[pos].block[top]=i;
file[pos].block_count++;
return i;
}
return -1;
}
void return_block(int pos) //釋放文件占用的磁盤塊,用于刪除文件時用
{
for(int i=0;i<file[pos].block_count;i++)
{
int temp=file[pos].block[i];
block_flag[temp]=0;
al_bflag[temp]++;
}
used_block-=file[pos].block_count;
}
int get_dir(int parent,char *dir_name) //創建目錄節點,成功則返回目錄的索引,失敗則返回-1
{
int index;
if(search(parent,dir_name,0,index)!=-1) //搜索在父目錄下是否有同名目錄,有則創建失敗
{
printf("Directory name repeated!\n");
return -1;
}
for(int i=1;i<DIR_NUM;i++) //搜索空閑的目錄節點
if(dir_flag[i]==0)
{ //登記并給目錄節點初始化
dir_flag[i]=1;
al_dflag[i]++;
al_dir[i]++;
used_dir++;
strcpy(dir[i].dir_name,dir_name);
dir[i].dir_count=0;
dir[i].file_count=0;
dir[i].parent=parent;
GetLocalTime(&dir[i].ctime); //獲得當前時間
return i;
}
return -1;
}
int get_file(int parent,char *file_name) //創建文件節點,成功則返回文件的索引號,失敗返回-1
{
int index;
if(search(parent,file_name,1,index)!=-1) //搜索在父目錄下是否有同名文件存在,有則創建失敗
{
printf("File name repeated!\n");
return -1;
}
for(int i=0;i<FILE_NUM;i++) //搜索空閑的文件節點
if(file_flag[i]==0)
{
strcpy(file[i].file_name,file_name);
file[i].block_count=0;
if(get_block(i)==-1) //給新創建的文件申請磁盤塊,如果失敗,創建文件
{ //將失敗
printf("Disk volumn error!\n");
return -1;
}
file_flag[i]=1;
al_fflag[i]++; //登記并給文件節點初始化
al_file[i]++;
used_file++;
file[i].file_length=0;
file[i].parent=parent;
GetLocalTime(&file[i].ctime); //獲得當前時間
return i;
}
return -1;
}
int get_buffer(int pos) //給文件申請緩沖區,打開文件時調用,失敗時返回-1
{
for(int i=0;i<BUF_NUM;i++)
if(buffer[i].flag==0)
{
buffer[i].flag=1; //修改使用標志并初始化
buffer[i].file_id=pos;
buffer[i].length=0;
buffer[i].offset=0;
return i;
}
return -1;
}
int get_buffer_id(int pos) //得到被打開文件的緩沖區索引號,失敗則返回-1
{
for(int i=0;i<BUF_NUM;i++)
if(buffer[i].flag==1 && buffer[i].file_id==pos)
return i;
return -1;
}
int create_file(int parent,char *file_name) //在指定的目錄下創建文件,如果創建成功則返回
{ //文件的索引號,否則返回-1
if(dir[parent].file_count==16) //如果父目錄已滿,則創建失敗
{
printf("Parent directory is full!\n");
return -1;
}
int pos=get_file(parent,file_name); //開始創建文件
if(pos==-1)
{
printf("Create file error!\n");
return -1;
}
struct dir_node *p=&dir[parent]; //修改父目錄的控制信息
int top=p->file_count;
p->child_file[top]=pos;
p->file_count++;
al_dir[parent]++;
return pos;
}
int create_dir(int parent,char *dir_name) //在指定的目錄下創建目錄,如果成功則返回目錄
{ //的索引號,否則返回-1
if(dir[parent].dir_count==8) //如果父目錄已滿,則創建失敗
{
printf("Parent directory is full!\n");
return -1;
}
int pos=get_dir(parent,dir_name); //開始創建目錄
if(pos==-1)
{
printf("Create directory error!\n");
return -1;
}
struct dir_node *p=&dir[parent]; //修改父目錄的控制信息
int top=p->dir_count;
p->child_dir[top]=pos;
p->dir_count++;
al_dir[parent]++;
return pos;
}
int md(char *name) //創建目錄的主調函數,它的參數只有用戶輸入
{ //如果創建成功,則返回目錄的索引號,否則
int parent,p=0; //返回-1
parent=get_parent(name,p);
if(parent==-1) //父目錄找不到,輸入有誤,創建失敗
{
printf("Path name error!\n");
return -1;
}
return create_dir(parent,name+p); //開始創建目錄
}
int rename_dir(char *old_name,char *new_name) //對目錄重命名,需要輸入兩個參數,如果
{ //成功返回目錄的索引號,否則返回-1
int parent,p=0,index;
parent=get_parent(old_name,p);
if(parent==-1) //找不到父目錄,輸入錯誤,重命名失敗
{
printf("Path name error!\n");
return -1;
}
int dir_id=search(parent,old_name+p,0,index); //找到父目錄,查找要重命名的目錄
if(dir_id==-1) //找不到該目錄,重命名失敗
{
printf("The directory not exist!\n");
return -1;
}
if(strcmp(old_name+p,new_name)!=0 && search(parent,new_name,0,index)!=-1)
{ //重命名后出現目錄重名,重命名失敗
printf("Dir name repeated!\n");
return -1;
}
strcpy(dir[dir_id].dir_name,new_name);
al_dir[dir_id]++;
return dir_id;
}
int create(char *name) //創建文件的主調函數,直接接受用戶輸入
{ //成功返回文件的索引號,否則返回-1
int parent,p=0;
parent=get_parent(name,p);
if(parent==-1) //找不到父目錄,輸入錯誤,創建失敗
{
printf("Path name error!\n");
return -1;
}
return create_file(parent,name+p); //開始創建文件
}
int rename_file(char *old_name,char *new_name) //對文件重命名,成功返回文件的索引號
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -