Demo entry 6339807

文件管理

   

Submitted by pw on Dec 25, 2016 at 15:21
Language: C. Code size: 17.6 kB.

#include<stdio.h>                          
#include<stdlib.h>
#include<string.h>
#include<iostream.h>


struct OpenFileTable              //打开文件表数据结构
{
	long   offset;            // 当前文件读写指针
	char file_name[10];       // 文件名数组
	long int file_start;      // 文件起始块号
	long int file_length;     // 文件长度(字节)
};

struct FCB_Block              //FCB数据结构
{
	int  flag;            // 标志,-1表示未用,1表示文件用
	char file_name[10];   // 文件名数组
	long int file_date;       // 文件建立日期
    long int file_time;       // 文件建立时间
	long int file_start;      // 文件起始块号
	long int file_length;     // 文件长度(字节)
};

struct Super_Block            // 超级块数据结构, 文件系统的分区信息,存放在0#物理块中
{ 
	unsigned long int fs_totalsize; // 整个分区的总磁盘物理块数 
	unsigned long int fs_freesize;  // 分区的所有空闲磁盘物理块数
	unsigned int fs_blocksize;  // 文件系统的物理块大小(字节)
	unsigned int fs_fat_start;  // FAT的起始磁盘物理块号 
	unsigned int fs_fat_size;   // FAT占用的磁盘物理块数
	unsigned int fs_dir_start;  // 根目录的起始磁盘物理块号
	unsigned int fs_dir_size;   // 根目录占用的磁盘物理块数
	unsigned int fs_data_start; // 数据区起始磁盘物理块号
	unsigned long int fs_data_size; // 数据区的磁盘物理块数
 };

const char DiskName[]="FileSys.dat";  //磁盘文件名
char rw_buffer[512];             // 读写使用的缓冲区
struct FCB_Block filefcb[130];   // 读写目录使用的数据结构
struct Super_Block FsSupBlk;     // 读写超级块使用的数据结构
long int fat_buffer[5000];       // 读写FAT使用的缓冲区,为简化在系统启动时全部装入内存,0为空闲
struct OpenFileTable OFT[16];    // 打开文件表,当前只使用OFT[0]


unsigned int block_size;           // 物理块大小(字节)
unsigned long int total_disk_size; // 磁盘总容量(物理块数)
unsigned int total_dir_size;       // 目录占有的物理块数
unsigned int total_fat_size;       // FAT占有的物理块数

long int find_fcb;  // 记录读FCB块的次数
FILE *fsPtr;        // 模拟磁盘的文件指针



/*********************** 磁盘块的申请***********************************/ 

unsigned long int Get_Block(unsigned long int count) //分配count个物理快,返回首块指针,其它已经连接
{
	unsigned long int tmp,firstblk,tmpcount;
	unsigned long int i;
    int flag=1;

	if (count > FsSupBlk.fs_freesize)
	{ printf("  ==== 没有足够磁盘容量,不能分配!==== \n"); return 0; }

    tmpcount=0;

    for(i=FsSupBlk.fs_data_start;i<=FsSupBlk.fs_totalsize;i++)//建立分配链
	{    
		if(fat_buffer[i] == 0)  //文件未占有,分配 
		{   
			if (flag==1)
			{  firstblk=i;  flag=-1;}
			else
			{  fat_buffer[tmp]=i;  }

			 tmp=i;
			 fat_buffer[i]=-1;
		     tmpcount++;
			 if(tmpcount==count)   //分配完成
			   { FsSupBlk.fs_freesize=FsSupBlk.fs_freesize-count;//减少可分配物理块
				 return firstblk; 
			   }
		} 
	}	
	return -1; //分配不成功
}
/*********************** 磁盘块的回收***********************************/ 

void Put_Block(unsigned long int addr) 
{  unsigned long int i,j;
   int count; 

   i=addr; count=0;
   while(fat_buffer[i]!=-1)
	{
	  j=fat_buffer[i]; //下一项
      fat_buffer[i] = 0; 
	  count++;
	  i=j;
	}	

   fat_buffer[i] = 0;

   FsSupBlk.fs_freesize=FsSupBlk.fs_freesize+count+1;//增加可分配物理块
 
   return;
}
/*********************** 读磁盘块***********************************/ 

void Read_Block(unsigned long int addr,char *buf) 
{
	if (addr>FsSupBlk.fs_totalsize)
	{ printf("  ==== 超出磁盘容量,不能读!==== \n"); return; }

	fseek(fsPtr,FsSupBlk.fs_blocksize*addr,SEEK_SET);
    fread(buf,512,1,fsPtr);
    
	return;
}
/*********************** 写磁盘块***********************************/ 

void Write_Block(unsigned long int addr,char *buf) 
{
	if (addr>FsSupBlk.fs_totalsize)
	{ printf("  ==== 超出磁盘容量,不能写!==== \n"); return; }

	fseek(fsPtr,FsSupBlk.fs_blocksize*addr,SEEK_SET);
    fwrite(buf,512,1,fsPtr);
    
	return;
}

/*********************** 格式化磁盘***********************************/ 

void Real_Format() 
{
	unsigned long int bcount;
     long int fatval,i;
	char *c;

	//更改系统超级块信息	  
  FsSupBlk.fs_totalsize=total_disk_size;     
  FsSupBlk.fs_blocksize=block_size; 

  FsSupBlk.fs_dir_start=1;  
  FsSupBlk.fs_dir_size=total_dir_size; 

  FsSupBlk.fs_fat_start=total_dir_size+1;   
  FsSupBlk.fs_fat_size=total_fat_size;  
 
  FsSupBlk.fs_data_start=FsSupBlk.fs_fat_start+FsSupBlk.fs_fat_size; 
  FsSupBlk.fs_data_size = FsSupBlk.fs_totalsize - FsSupBlk.fs_dir_size - FsSupBlk.fs_fat_size-1; 
    
  FsSupBlk.fs_freesize= FsSupBlk.fs_data_size;

 
 
  	
	//初始化目录   
	for(i=0;i<128;i++) filefcb[i].flag=-1;          //为-1表示FCB未使用
	fseek(fsPtr,512L,SEEK_SET);
	fwrite(&filefcb[0],sizeof(struct FCB_Block),128,fsPtr);	

	  //初始化FAT
      fatval=FsSupBlk.fs_fat_start*512;
	  fseek(fsPtr,fatval,SEEK_SET);     //定位文件指针  
      
	  bcount=FsSupBlk.fs_fat_size+FsSupBlk.fs_dir_size+1; 
	  for(i=0;i<bcount;i++) fat_buffer[i]=-1;   //标记已经使用的磁盘数据块,即FAT区、目录区和启动区
	  for(;i<FsSupBlk.fs_totalsize;i++) fat_buffer[i]=0;   //为0表示为空的物理快
	  
	  fwrite(&fat_buffer[0],sizeof(long int),FsSupBlk.fs_totalsize,fsPtr);

    
	  
	  //初始化数据区
	  for(i=0;i<512;i++) rw_buffer[i]=' ';//缓冲区清空
	  for(i=FsSupBlk.fs_data_start;i<FsSupBlk.fs_totalsize;i++)
		   Write_Block(i,rw_buffer);  //缓冲区写入第i块


	 
}
/***********************新建系统磁盘文件		***********************************/ 
void Create_Disk()                  
{
	long int i;
	unsigned long int total;

	fsPtr=fopen(DiskName,"wb+");
	if(fsPtr==NULL)
	{
		printf(" 不能建立磁盘所需的文件 !\n");
		exit(0);
	}

   //  建立磁盘文件

   total=total_disk_size;

   for(i=0;i<total;i++) //建立大小为total的磁盘文件
	    fwrite(rw_buffer,512,1,fsPtr); 
   fclose(fsPtr); 

   fsPtr=fopen(DiskName,"rb+");

   Real_Format();

  return;
}


/***********************读写系统超级块信息***********************************/ 

void Read_Boot()   //读取磁盘超级块数据信息
{
    rewind(fsPtr);
	fread(&FsSupBlk,sizeof(struct Super_Block),1,fsPtr);

	return;	
}


void FileBoot()  //超级块数据信息存盘
{	
    rewind(fsPtr);
	fwrite(&FsSupBlk,sizeof(struct Super_Block),1,fsPtr);
	
	return;	
}


/***********************FAT操作***********************************/ 

void LoadFat()  //装载全部FAT到内存
{	
    fseek(fsPtr,FsSupBlk.fs_fat_start*512,SEEK_SET);
	
	fread(fat_buffer,sizeof(long int),FsSupBlk.fs_totalsize ,fsPtr);	
	return;	
}

void SaveFat()  //FAT到文件FAT区
{	
    
	fseek(fsPtr,FsSupBlk.fs_fat_start*512,SEEK_SET);

	fwrite(fat_buffer,sizeof(long int),FsSupBlk.fs_totalsize,fsPtr);
	return;	
}

/***********************显示超级块信息***********************************/ 
void boot_dis()
{
  printf("FsSupBlk.fs_totalsize=%ld\n",FsSupBlk.fs_totalsize);     
  printf("FsSupBlk.fs_blocksize=%d\n",FsSupBlk.fs_blocksize); 
  printf("FsSupBlk.fs_dir_start=%d\n",FsSupBlk.fs_dir_start);  
  printf("FsSupBlk.fs_dir_size=%d\n",FsSupBlk.fs_dir_size); 
  printf("FsSupBlk.fs_fat_start=%d\n",FsSupBlk.fs_fat_start);   
  printf("FsSupBlk.fs_fat_size=%d\n",FsSupBlk.fs_fat_size);  
  printf("FsSupBlk.fs_data_start=%d\n",FsSupBlk.fs_data_start); 
  printf("FsSupBlk.fs_data_size=%ld\n",FsSupBlk.fs_data_size); 
  printf("FsSupBlk.fs_freesize=%ld\n",FsSupBlk.fs_freesize);

}


 /***********************系统初始化***********************************/ 

void Sys_Init() //初始化
{
	fsPtr=fopen(DiskName,"rb+");	
	if(fsPtr == NULL) Create_Disk();

    Read_Boot();
	//boot_dis();    
    LoadFat();
	return;		
}
/***********************显示操作***********************************/ 

 
void dir()        //显示目录下的文件 
{
	int i,countFile=0;
    char str[16];
    long int n,pos_dir,pos_fat;

	cout<<endl;

    pos_dir=FsSupBlk.fs_dir_start*512;
    pos_fat=FsSupBlk.fs_fat_start*512;

	fseek(fsPtr,pos_dir,SEEK_SET);
	while(ftell(fsPtr)<pos_fat)
	{
	    fread(&filefcb[0],sizeof(struct FCB_Block),16 ,fsPtr);		
        for(i=0;i<16;i++)
         if(filefcb[i].flag == 1)  //文件占有 
		 {
			countFile++;
            n = filefcb[i].file_length; 
            printf("   %-15s<%s>%15d bytes\n", filefcb[i].file_name,"file",n); 
		 } 
	 }
	cout<<endl;

	printf("  总共有 %d 个文件\n",countFile);
	printf("  系统总共有 %ld 个物理块可用\n\n",FsSupBlk.fs_freesize);

} 
/*************************查找文件*******************************/ 

//查找文件,文件存在返回当前FCB数组下标,否则返回-1

int Find_File(char *filename) 
{
	int i;
	long int pos_dir,pos_fat;
	
    pos_dir=FsSupBlk.fs_dir_start*512;
    pos_fat=FsSupBlk.fs_fat_start*512;
    find_fcb=0;
	fseek(fsPtr,pos_dir,SEEK_SET);
	while(ftell(fsPtr)<pos_fat)
	{   find_fcb++;
	    fread(&filefcb[0],sizeof(struct FCB_Block),16 ,fsPtr);	
        for(i=0;i<16;i++)
         if(filefcb[i].flag!=-1)
		 { if(strcmp(filename,filefcb[i].file_name) == 0) return i;} //文件存在 	
        
	 }

    return -1;
}

/*************************创建文件*******************************/ 

void create(char *fname,long int num)  //在当前目录下创建一个名字为str的文件,长度为num 
{
    int i,j;      //true表示没有与该名字重名的文件 
    int tempnode; 
	long int pos_dir,getnum=0;
	unsigned long int blkcount;

	blkcount= num/512+1; //计算需要的物理块
	
    if(FsSupBlk.fs_freesize < blkcount) //磁盘没有足够空间
	{ 
		printf("\n 磁盘没有足够空间,不能建立 !\n\n"); 
		return;
	}

	tempnode=Find_File(fname);

	if (tempnode!=-1) //表示文件存在
	{ printf("\n 文件已经存在,不需要建立 !\n\n"); return;}


	//  建立文件的处理
	
    pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize;
	fseek(fsPtr,pos_dir,SEEK_SET);  //定位到目录区
  
	for(i=0; i<FsSupBlk.fs_dir_size; i++)	
	{   
		//Read_Block(i+FsSupBlk.fs_dir_start,(char *)filefcb);

		fread(&filefcb[0],sizeof(struct FCB_Block),16 ,fsPtr);	
        for(j=0;j<16;j++)
			if(filefcb[j].flag == -1) //找到空目录项
			{
				// 分配空间, 标记FCB数据项,并将FCB写磁盘

				getnum=Get_Block(blkcount);
				if(getnum==-1){ printf("不能分配存储空间 \n");return;}

				filefcb[j].file_start=getnum;
				filefcb[j].flag = 1;
				filefcb[j].file_length=num;
				strcpy(filefcb[j].file_name,fname);

				//filefcb[].file_time=
				//filefcb[].file_date=
				
				// 改变磁盘FCB值 
				pos_dir=pos_dir+sizeof(struct FCB_Block)*(i*16+j);
				fseek(fsPtr,pos_dir,SEEK_SET);            //定位到目录区的FCB项
				fwrite(&filefcb[j],sizeof(struct FCB_Block),1 ,fsPtr);

	            //Write_Block(i+FsSupBlk.fs_dir_start,(char *)filefcb);

	            printf("  文件占用了 %d 个物理块\n",blkcount);
	            printf("  系统还有 %ld 个物理块可用\n\n",FsSupBlk.fs_freesize);
				return;
			}       
	}
    //没有FCB项,不能建立文件
    cout<<"当前没有足够的目录区,不能建立文件 ! "<<endl; 
    return;  
	
} 

/*************************格式化*******************************/ 


void format()
{
	char ch;
    cout<<"\n 真希望格式化磁盘吗?(y/n) ";
    cin>>ch;
    if(ch=='y'||ch=='Y')
	{
	    Real_Format();
	    printf("\n Format Successful!\n\n");
	}	
}


/****************************删除文件操作**************************************/ 
void del(char *fname) 
{ 
	long int tempnode;
	long int pos_dir;

	tempnode=Find_File(fname);
	if (tempnode==-1) //表示文件不存在
	{ printf("\n 文件不存在,不能删除 !\n\n"); return;}

	//  删除文件的处理
	
    Put_Block(filefcb[tempnode].file_start);  // 释放文件存储空间
    filefcb[tempnode].flag =-1;               // 标记FCB项可用
    
	// 修改的FCB项写回磁盘
	pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize+((find_fcb-1)*16+tempnode)*sizeof(struct FCB_Block);
	fseek(fsPtr,pos_dir,SEEK_SET);  //定位到目录区
	fwrite(&filefcb[tempnode],sizeof(struct FCB_Block),1 ,fsPtr);
	
	return;
} 

/*************************写文件*******************************/ 


void write(char *fname ,int num)//写文件,仅实现在文件尾部填加内容,并限制在512个字节内
{
    int tempnode;
    int i,j,x;
	int rescount;
	long int pos_dir;
    

	  if (num > 512)               
	  { 
		  printf("\n 不能写大于512字节的数据 !\n\n"); 
		  return; 
	  }
	  tempnode=Find_File(fname);
	  if (tempnode==-1)               //表示文件不存在
	  { 
		  printf("\n 文件不存在,不能写 !\n\n"); 
		  return;
	  }
	 
	//  写文件的处理

	char *string=new char [num]; //申请空间
	for(i=0;i<num;i++)
		{
	   	   cin>>string[i];		 
		}
 
	rescount=filefcb[tempnode].file_length % FsSupBlk.fs_blocksize; 
    if (num> FsSupBlk.fs_blocksize-rescount)
	{
		if (FsSupBlk.fs_freesize<1) 
		{
			printf("\n 文件系统没有足够空间,不能写 !\n\n");
			return;
		}
	}

	for(j=filefcb[tempnode].file_start;fat_buffer[j]!=-1;j=fat_buffer[j]); 
	Read_Block(j,rw_buffer); 
	
    if (num<= FsSupBlk.fs_blocksize-rescount)
	{
		for(i=0;i<num;i++) 	rw_buffer[rescount+i]=string[i];
		Write_Block(j,rw_buffer); 
	}
	else 
	{
     
       for(i=0;i<FsSupBlk.fs_blocksize-rescount;i++) 
			rw_buffer[rescount+i]=string[i];
	   Write_Block(j,rw_buffer);
   
       fat_buffer[j]=Get_Block(1);
       j=fat_buffer[j];
       for(x=0;x<FsSupBlk.fs_blocksize;x++) rw_buffer[x]=' ';
       for(x=0;x<num-(FsSupBlk.fs_blocksize-rescount);x++) 
			rw_buffer[x]=string[i+x];
	   Write_Block(j,rw_buffer); 
	}
    //delete []string;
	// 修改FCB项并写回磁盘
    filefcb[tempnode].file_length+=num;     // 增加文件的长度
	pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize+((find_fcb-1)*16+tempnode)*sizeof(struct FCB_Block);
	fseek(fsPtr,pos_dir,SEEK_SET);  //定位到目录区
	fwrite(&filefcb[tempnode],sizeof(struct FCB_Block),1 ,fsPtr);
    cin.ignore(10000,'\n'); //清除输入流缓冲区
	cout<<endl<<"=================== 写文件完成!=============="<<endl;	
	return;
}



void copyFcbtoOft(int fcbpos)
{
	OFT[0].offset =0;
	strcpy(OFT[0].file_name,filefcb[fcbpos].file_name);
    OFT[0].file_start = filefcb[fcbpos].file_start ;
    OFT[0].file_length= filefcb[fcbpos].file_length ;
}

/*************************读文件*******************************/ 

void read(char *fname,long start,int count)//读文件 ,限制在512个字节内
{
    int tempnode;
	int stblknum,offset;
    int dspnum;
	long i,j,x;

	  tempnode=Find_File(fname);    
	  if (tempnode==-1)              //表示文件不存在
	  { printf("\n 文件不存在,不能读 !\n\n");
	    return;  }

	  if (start > filefcb[tempnode].file_length)  //读的数据超出文件范围
	  { printf("\n 超出文件范围,不能读 !\n\n"); 
	    return;  }
	
	  //  读文件的处理
   printf("\n========================================\n");
    stblknum=start/FsSupBlk.fs_blocksize+1; // 起始物理块
    offset=start%FsSupBlk.fs_blocksize;     // 起始物理块的偏移量
	if(start+count>filefcb[tempnode].file_length )
		 count= filefcb[tempnode].file_length-start;

	for(i=filefcb[tempnode].file_start,j=1;j<stblknum;j++)
		i=fat_buffer[i]; 
	Read_Block(i,rw_buffer); 
    if(start+count>filefcb[tempnode].file_length )
		 count= filefcb[tempnode].file_length-start;
	if(count<=FsSupBlk.fs_blocksize-offset) 
	{
		for(j=0;j<count;j++) cout<<rw_buffer[j+offset];
	}
	else 
	{
	  for(j=0;j<FsSupBlk.fs_blocksize-offset;j++) cout<<rw_buffer[j+offset];
      dspnum=(count-(FsSupBlk.fs_blocksize-offset))/FsSupBlk.fs_blocksize+1;
      for(j=0;j<dspnum-1;j++) 
	  {	  
		  i=fat_buffer[i]; 
		  Read_Block(i,rw_buffer); 
		  for(x=0;x<FsSupBlk.fs_blocksize;x++) 
			  cout<<rw_buffer[x];
	  }
	  i=fat_buffer[i];
	  Read_Block(i,rw_buffer); 
	  x=(count-(FsSupBlk.fs_blocksize-offset))%FsSupBlk.fs_blocksize;
	  for(j=0;j<x;j++) cout<<rw_buffer[x];
	}
	
	cout<<endl<<"============= 读文件完成!================"<<endl;	
	return;
}

/*************************显示帮助*******************************/ 


void display_help()
{	
	printf("   写文件           wf filename size \n");

	printf("   读文件           rf filename start size \n");

	printf("   删除文件         df filename \n");

	printf("   建立文件         cf filename size \n");	

	printf("   显示文件         dir \n");

	printf("   磁盘格式化       format \n");
	
	printf("   退出文件系统     quit \n\n");
}


/*************************命令解释*******************************/ 

void CmdShell()  //全部命令的解释执行过程
{	
	
	int j;
	int parameter;     // 记录命令行参数个数
	int len;           // 输入的命令行长度
	char string[50];   // 输入的命令行字符串
	char *str[4];      // 分解出的命令行参数
	bool flag;         // 标志

	cout<<"\n  输入help查看所有命令"<<endl<<endl;

    while(1) 
	{
		printf("c:\>");     //输出系统提示符
	
        gets(string); 
        len = strlen(string); 

        //命令行信息的解析过程 
        
		for(parameter = 0, flag = true, j = 0; j<len ; j++) 
		{
            if(string[j] == ' ')   //读到输入字符为空格时,输出回车
			{   flag = true;   string[j] = '\0'; 	} 
            else 
				if(flag) 
				{   flag = false;                 
                    str[parameter++] = &string[j]; //分解出的命令,以空格为各参数														的分割符 
				}                              //第一个为操作命令,其他为参数
		}  
        
		
	  strlwr(str[0]);	
	  // 根据操作命令执行不同的过程

      if(!strcmp("cf",str[0]))    // 创建文件 
	   {
		  if(parameter != 3)
		    printf(" 格式不正确,请重新输入 ! \n "); 
		  else 
			  create(str[1],atol(str[2]));  }  // 创建一个名字为str[0]大小为str[2]的文件
      else  if(!strcmp("df",str[0]))           // 删除文件
	  { if(parameter != 2)                 
		   printf(" 格式不正确,请重新输入 ! \n "); 		
         else 
			 //disfat();}
	        del(str[1]); }            //删除文件str[1]		
      else if(!strcmp("dir",str[0]))   //显示文件命令 
                dir(); 
      else if(!strcmp("help",str[0])) 
                display_help();
      else if(!strcmp("format",str[0]))
				format();
	  else if(!strcmp("wf",str[0]))      //写文件
	  { if(parameter != 3)                 
		  printf(" 格式不正确,请重新输入 ! \n "); 		
         else 
		  write(str[1],atol(str[2])); }  		
	  else if(!strcmp("rf",str[0])) //读文件内容
	  { if(parameter != 4)                 
		   printf(" 格式不正确,请重新输入 !\n"); 			
         else 
		   read(str[1],atol(str[2]),atol(str[3]));   } 	
	  else if(!strcmp("quit",str[0])) //退出
		 {  SaveFat();  fclose(fsPtr);  exit(0);}	
      else 
	   if (parameter >0 ) cout<<"命令错误!"<<endl;

	} 
}

/************************* 主过程 *******************************/ 

void main()
{	
	block_size=512;      // 物理块大小512字节
    total_disk_size=4096;   // 磁盘总容量为4096块
    total_dir_size=16;  // 目录占有的物理块数为16块
	total_fat_size=32;  // FAT占有的物理块数为32块

	Sys_Init();    //初始化磁盘系统	
	CmdShell();    //命令解释过程
}

This snippet took 0.03 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).