c++實現的十分簡易檔案系統
課題作業任務:在記憶體中開闢一個100M的空間作為磁碟空間,在此上模擬建立一個檔案管理系統。
本系統已經實現的相關操作:
所有操作都不支援從根目錄索引,即都只能訪問當前目錄下的檔案,不能用/a/b越級訪問
1)目錄相關操作
列出目錄下所有檔案:ls
切換目錄:cd newdir
顯示目錄:pwd
建立目錄:mkdir dirName
刪除目錄和目錄下所有檔案:rmdir dirName
修改目錄名或檔名:mv oldName newName
2)檔案相關操作
建立檔案(大小以1KB為單位):touch filename fileSize
刪除檔案:rm filename
從上一次後讀取size位元組的檔案內容:read fileName size
從頭開始讀取size位元組的檔案內容:reread fileName size
從檔案尾寫入內容:write fileName content
清空檔案,從頭寫入:rewrite fileName content
3)系統操作
使用命令幫助:help
退出系統:quit
全部程式碼大概有600多行,是一個非常簡單的實現,不適合想要深入瞭解的人觀看,網上有其他的功能較為強大實現,程式碼都在上千,比較具有學習的價值。
點選開啟連結(很強大,我自己也還沒有仔細看)
點選開啟連結(程式碼好像有點問題)
1. 系統層次結構:
系統介面:是該檔案系統提供給使用者可以使用的命令介面,如ls,mkdir,touch等
檔案管理:是系統對於檔案和目錄層次的管理的,規定了FCB結構,目錄結構等,包含了對介面的實現。
磁碟管理:是系統最底層直接對記憶體空間的管理,如磁碟空閒空間管理,磁碟空間的分配方式等。
2. 磁碟管理
盤塊大小:以1KB的空間作為系統盤塊,用以分配的基本單位
分配方式:系統採用連續分配的方式,在磁碟上劃定要求的連續盤塊分配給檔案使用
空間管理:系統採用位示圖的方法,標記了磁碟上所有盤塊的使用情況。
使用systemStartAddr標記了整個系統的起始地址,以1KB作為盤塊劃分,所以本系統共有100K個盤塊。位示圖用char[]表示,所以位示圖大小為100KB。位示圖儲存在系統起始位置,在系統初始化時,0~99號盤塊預設被儲存位示圖使用。
磁碟向檔案管理提供的介面說明:
DiskOperate.h#ifndef DISKOPERATE_H_INCLUDED
#define DISKOPERATE_H_INCLUDED
//磁碟操作介面
#define system_size 100*1024*1024 //系統大小
#define block_szie 1024 //盤塊大小
#define block_count system_size/block_szie //系統盤塊數目
//初始化系統
void initSystem();
//磁碟分配
int getBlock(int blockSize) ;
//獲得盤塊的實體地址
char* getBlockAddr(int blockNum);
//獲得實體地址的盤塊號
int getAddrBlock(char* addr);
//釋放盤塊、
int releaseBlock(int blockNum, int blockSize);
//退出系統
void exitSystem();
#endif // DISKOPERATE_H_INCLUDED
3.檔案層次管理說明
FileOperate.h (部分內容)//目錄項結構:
struct dirUnit{
char fileName[59]; //檔名
char type; //檔案型別,0目錄, 1檔案
int startBlock; //FCB起始盤塊
};
//一個目錄項包含了檔名和檔案型別,當檔案為目錄時,起始盤塊指示了目錄表所在的盤塊號,當檔案為檔案時,起始盤塊指示了FCB所在的盤塊號。
#define dirTable_max_size 15 //目錄表項最大值
//目錄表結構:
struct dirTable {
int dirUnitAmount;//目錄項數目
dirUnit dirs[dirTable_max_size];//目錄項列表
};
/*
本系統規定一個目錄表只佔用一個盤塊,一個目錄項大小為64B,所以一個目錄表中最多可含15個目錄項,dirUnitAmount記錄每個目錄表中已含有的目錄項數目。系統在初始化時,會自動生成一個空的根目錄表存放於磁碟中,作為使用者的初始位置,使用者所有的目錄和檔案都這個表為根進行樹狀目錄結構的展開。
當建立一個目錄表時,系統會自動為目錄表加上一項名為”..”的目錄項,指示父目錄表的位置。
*/
//FCB結構:
struct FCB {
int blockNum; //檔案資料起始盤塊號
int fileSize; //檔案大小,盤塊為單位
int dataSize; //已寫入的內容大小,位元組為單位
int readptr; //讀指標,位元組為單位
int link; //檔案連結數
};
/*
檔案控制塊包含了檔案資料的起始位置和大小。dataSize,readptr是為檔案的讀寫操作而準備的,記錄檔案已寫入的內容長度(不可超過檔案大小),和當前讀取的位置。Link記錄了檔案的連結數,用於檔案的共享,當檔案的連結數為0時,系統可以回收檔案的空間。同樣的,一個FCB大小為20B,但也用一個盤塊儲存。
由於採用的是連續分配方式,所以系統規定檔案被建立時,必須給出檔案的大小,而且後期也不能修改檔案的大小。
*/
看到這裡,如果你有修過計算機系統的話,你就會發現我採取了一種最簡單的實現方式,都說了十分簡易嘛~~
系統用char[]陣列作為位示圖儲存了每一個盤塊的使用狀態,而且採取了連續分配的方式,對於目錄表和FCB都規定直接使用一個盤塊,檔案又是規定好大小不能擴充套件的,所以實現起來減少了很多FAT,索引表,那些離散分配所需的連線方式,單純練手的話,還是十分簡易的。
具體實現
1. 磁碟管理的實現
這部分比較簡單,程式碼備註也很詳細了,可以直接看程式碼
DiskOperate.cpp
#include"DiskOperate.h"
#include<stdio.h>
#include<stdlib.h>
char* systemStartAddr; //系統起始地址
//初始化系統
void initSystem()
{
//建立空間
systemStartAddr = (char*)malloc(system_size * sizeof(char));
//初始化盤塊的位示圖
for(int i=0; i<block_count; i++)
systemStartAddr[i] = '0';
//用於存放位示圖的空間已被佔用
int bitMapSize = block_count * sizeof(char) / block_szie;//位示圖佔用盤塊數:100
for(int i=0; i<bitMapSize; i++)//從零開始分配
systemStartAddr[i] = '1'; //盤塊已被使用
}
//退出系統
void exitSystem()
{
free(systemStartAddr);
}
//磁碟分配
int getBlock(int blockSize)
{
int startBlock = 0;
int sum=0;
for(int i=0; i<block_count; i++)
{
if(systemStartAddr[i] == '0')//可用盤塊
{
if(sum == 0)//剛開始,設定開始盤塊號
startBlock = i;
sum++;
if(sum == blockSize)//連續盤塊是否滿足需求
{
//滿足分配,置1
for(int j=startBlock; j<startBlock+blockSize; j++)
systemStartAddr[j] = '1';
return startBlock;
}
}
else//已被使用,連續已經被打斷
sum = 0;
}
printf("not found such series memory Or memory is full\n");
return -1;
}
//獲得盤塊的實體地址
char* getBlockAddr(int blockNum)
{
return systemStartAddr + blockNum * block_szie; //偏移量單位為位元組
}
//獲得實體地址的盤塊號
int getAddrBlock(char* addr)
{
return (addr - systemStartAddr)/block_szie;
}
//釋放盤塊、
int releaseBlock(int blockNum, int blockSize)
{
int endBlock = blockNum + blockSize;
//修改位示圖盤塊的位置為0
for(int i=blockNum; i<endBlock; i++)
systemStartAddr[i] = '0';
return 0;
}
2.檔案管理
首先說明全域性變數dirTable* rootDirTable; //根目錄
dirTable* currentDirTable; //當前所在目錄位置
char path[200]; //儲存當前絕對路徑
結構體定義可以見上面檔案管理1)建立檔案:touch fileName size
建立檔案的過程可以為:
為檔案控制塊申請空間->為檔案資料申請空間->建立FCB控制塊->在當前目錄新增相關的目錄項描述
//建立檔案
int creatFile(char fileName[], int fileSize)
{
//檢測檔名字長度
if(strlen(fileName) >= 59)
{
printf("file name too long\n");
return -1;
}
//獲得FCB的空間
int FCBBlock = getBlock(1);
if(FCBBlock == -1)
return -1;
//獲取檔案資料空間
int FileBlock = getBlock(fileSize);
if(FileBlock == -1)
return -1;
//建立FCB
if(creatFCB(FCBBlock, FileBlock, fileSize) == -1)
return -1;
//新增到目錄項
if(addDirUnit(currentDirTable, fileName, 1, FCBBlock) == -1)
return -1;
return 0;
}
//建立FCB
int creatFCB(int fcbBlockNum, int fileBlockNum, int fileSize)
{
//找到fcb的儲存位置
FCB* currentFCB = (FCB*) getBlockAddr(fcbBlockNum);
currentFCB->blockNum = fileBlockNum;//檔案資料起始位置
currentFCB->fileSize = fileSize;//檔案大小
currentFCB->link = 1;//檔案連結數
currentFCB->dataSize = 0;//檔案已寫入資料長度
currentFCB->readptr = 0;//檔案讀指標
return 0;
}
//新增目錄項
int addDirUnit(dirTable* myDirTable, char fileName[], int type, int FCBBlockNum)
{
//獲得目錄表
int dirUnitAmount = myDirTable->dirUnitAmount;
//檢測目錄表示是否已滿
if(dirUnitAmount == dirTable_max_size)
{
printf("dirTables is full, try to delete some file\n");
return -1;
}
//是否存在同名檔案
if(findUnitInTable(myDirTable, fileName) != -1)
{
printf("file already exist\n");
return -1;
}
//構建新目錄項
dirUnit* newDirUnit = &myDirTable->dirs[dirUnitAmount];
myDirTable->dirUnitAmount++;//當前目錄表的目錄項數量+1
//設定新目錄項內容
strcpy(newDirUnit->fileName, fileName);
newDirUnit->type = type;
newDirUnit->startBlock = FCBBlockNum;
return 0;
}
//從目錄中查詢目錄專案
int findUnitInTable(dirTable* myDirTable, char unitName[])
{
//獲得目錄表
int dirUnitAmount = myDirTable->dirUnitAmount;
int unitIndex = -1;
for(int i=0; i<dirUnitAmount; i++)//查詢目錄項位置
if(strcmp(unitName, myDirTable->dirs[i].fileName) == 0)
unitIndex = i;
return unitIndex;
}
2)刪除檔案:rm fileName
刪除檔案的流程可以分為:
查詢檔案在當前目錄的目錄項描述內容->得到FCB的描述內容->釋放FCB空間和檔案資料空間->從目錄表中刪除檔案的目錄項
(也就是說,在這裡其實只是把使用者能得到檔案的索引刪除,而檔案的內容在沒有被覆蓋之前依舊是存在的)
//刪除檔案
int deleteFile(char fileName[])
{
//忽略系統的自動建立的父目錄
if(strcmp(fileName, "..") == 0)
{
printf("can't delete ..\n");
return -1;
}
//查詢檔案的目錄項位置
int unitIndex = findUnitInTable(currentDirTable, fileName);
if(unitIndex == -1)
{
printf("file not found\n");
return -1;
}
dirUnit myUnit = currentDirTable->dirs[unitIndex];
//判斷型別
if(myUnit.type == 0)//目錄
{
printf("not a file\n");
return -1;
}
int FCBBlock = myUnit.startBlock;
//釋放記憶體
releaseFile(FCBBlock);
//從目錄表中剔除
deleteDirUnit(currentDirTable, unitIndex);
return 0;
}
//釋放檔案記憶體
int releaseFile(int FCBBlock)
{
FCB* myFCB = (FCB*)getBlockAddr(FCBBlock);
myFCB->link--; //連結數減一
//無連結,刪除檔案
if(myFCB->link == 0)
{
//釋放檔案的資料空間
releaseBlock(myFCB->blockNum, myFCB->fileSize);
}
//釋放FCB的空間
releaseBlock(FCBBlock, 1);
return 0;
}
//刪除目錄項
int deleteDirUnit(dirTable* myDirTable, int unitIndex)
{
//遷移覆蓋
int dirUnitAmount = myDirTable->dirUnitAmount;
for(int i=unitIndex; i<dirUnitAmount-1; i++)
{
myDirTable->dirs[i] = myDirTable->dirs[i+1];
}
myDirTable->dirUnitAmount--;
return 0;
}
3)目錄的刪除和建立
目錄的建立和刪除與檔案的操作大致相同,建立目錄時,目錄表項的startBlock不是FCB而是指目錄的存放位置,而且還要自動為其新增多一個父目錄項“..”,用於跳轉。刪除目錄時需要注意是否遞迴刪除目錄下的所有檔案和目錄。詳請看最後的完整程式碼,這裡不專門複述。4)切換目錄: cd dirName
cd指令,主要就是讓當前目錄currentDirTable指向新的目錄盤塊地址就可以了,目錄盤塊地址可以在當前目錄表的表項中找到。
//切換目錄
int changeDir(char dirName[])
{
//目錄項在目錄位置
int unitIndex = findUnitInTable(currentDirTable, dirName);
//不存在
if(unitIndex == -1)
{
printf("file not found\n");
return -1;
}
if(currentDirTable->dirs[unitIndex].type == 1)
{
printf("not a dir\n");
return -1;
}
//修改當前目錄
int dirBlock = currentDirTable->dirs[unitIndex].startBlock;
currentDirTable = (dirTable*)getBlockAddr(dirBlock);
//修改全域性絕對路徑path
if(strcmp(dirName, "..") == 0)
{
//回退絕對路徑
int len = strlen(path);
for(int i=len-2;i>=0;i--)
if(path[i] == '\\')
{
path[i+1]='\0';
break;
}
}else {
strcat(path, dirName);
strcat(path, "\\");
}
return 0;
}
5)讀檔案:read fileName size
主要就是獲得檔案的初始地址,然後根據需要的讀取長度size和當前的讀指標進行輸出,如果遇到檔案尾則輸出#,讀寫的單位都是位元組
//讀檔案 read
int read(char fileName[], int length)
{
int unitIndex = findUnitInTable(currentDirTable, fileName);
if(unitIndex == -1)
{
printf("file no found\n");
return -1;
}
//控制塊
int FCBBlock = currentDirTable->dirs[unitIndex].startBlock;
FCB* myFCB = (FCB*)getBlockAddr(FCBBlock);
doRead(myFCB, length);
return 0;
}
//執行讀操作
int doRead(FCB* myFCB, int length)
{
//讀資料
int dataSize = myFCB->dataSize;
char* data = (char*)getBlockAddr(myFCB->blockNum);
//在不超出資料長度下,讀取指定長度的資料
for(int i=0; i<length && myFCB->readptr < dataSize; i++, myFCB->readptr++)
{
printf("%c", *(data+myFCB->readptr));
}
if(myFCB->readptr == dataSize)//讀到檔案末尾用#表示
printf("#");
//換行美觀
printf("\n");
return 0;
}
reread就是先把讀指標readptr置為0,然後執行讀操作。
6)寫檔案操作:write fileName content
和讀檔案差不多,不過是根據當前檔案的資料長度,在檔案末尾給檔案以位元組的形式賦值上輸入的content內容,資料長度不能超過檔案長度
//寫檔案,從末尾寫入 write
int write(char fileName[], char content[])
{
int unitIndex = findUnitInTable(currentDirTable, fileName);
if(unitIndex == -1)
{
printf("file no found\n");
return -1;
}
//控制塊
int FCBBlock = currentDirTable->dirs[unitIndex].startBlock;
FCB* myFCB = (FCB*)getBlockAddr(FCBBlock);
doWrite(myFCB, content);
return 0;
}
//執行寫操作
int doWrite(FCB* myFCB, char content[])
{
int contentLen = strlen(content);
int fileSize = myFCB->fileSize * block_szie;
char* data = (char*)getBlockAddr(myFCB->blockNum);
//在不超出檔案的大小的範圍內寫入
for(int i=0; i<contentLen && myFCB->dataSize<fileSize; i++, myFCB->dataSize++)
{
*(data+myFCB->dataSize) = content[i];
}
if(myFCB->dataSize == fileSize)
printf("file is full,can't write in\n");
return 0;
}
7)展示目錄下所有檔案:ls
對目錄表進行遍歷,同時根據檔案型別做出不同的輸出就可以了
//展示當前目錄 ls
void showDir()
{
int unitAmount = currentDirTable->dirUnitAmount;
printf("total:%d\n", unitAmount);
printf("name\ttype\tsize\tFCB\tdataStartBlock\n");
//遍歷所有表項
for(int i=0; i<unitAmount; i++)
{
//獲取目錄項
dirUnit unitTemp = currentDirTable->dirs[i];
printf("%s\t%d\t", unitTemp.fileName, unitTemp.type);
//該表項是檔案,繼續輸出大小和起始盤塊號
if(unitTemp.type == 1)
{
int FCBBlock = unitTemp.startBlock;
FCB* fileFCB = (FCB*)getBlockAddr(FCBBlock);
printf("%d\t%d\t%d\n", fileFCB->fileSize, FCBBlock, fileFCB->blockNum);
}else{
int dirBlock = unitTemp.startBlock;
dirTable* myTable = (dirTable*)getBlockAddr(dirBlock);
printf("%d\t%d\n",myTable->dirUnitAmount, unitTemp.startBlock);
}
}
}
8)FileOperate.cpp
幾乎全部的內容都在上面做了闡述了
#include"FileOperate.h"
#include<string.h>
#include<stdio.h>
dirTable* rootDirTable; //根目錄
dirTable* currentDirTable; //當前位置
char path[200]; //儲存當前絕對路徑
//初始化根目錄
void initRootDir()
{
//分配一個盤塊空間給rootDirTable
int startBlock = getBlock(1);
if(startBlock == -1)
return;
rootDirTable = (dirTable*)getBlockAddr(startBlock);
rootDirTable->dirUnitAmount = 0;
//將自身作為父級目錄
//addDirUnit(rootDirTable, "..", 0, startBlock);
currentDirTable = rootDirTable;
//初始化初始絕對路徑
path[0]='\\';
path[1]='\0';
}
//獲得絕對路徑
char* getPath()
{
return path;
}
//展示當前目錄 ls
void showDir()
{
int unitAmount = currentDirTable->dirUnitAmount;
printf("total:%d\n", unitAmount);
printf("name\ttype\tsize\tFCB\tdataStartBlock\n");
//遍歷所有表項
for(int i=0; i<unitAmount; i++)
{
//獲取目錄項
dirUnit unitTemp = currentDirTable->dirs[i];
printf("%s\t%d\t", unitTemp.fileName, unitTemp.type);
//該表項是檔案,繼續輸出大小和起始盤塊號
if(unitTemp.type == 1)
{
int FCBBlock = unitTemp.startBlock;
FCB* fileFCB = (FCB*)getBlockAddr(FCBBlock);
printf("%d\t%d\t%d\n", fileFCB->fileSize, FCBBlock, fileFCB->blockNum);
}else{
int dirBlock = unitTemp.startBlock;
dirTable* myTable = (dirTable*)getBlockAddr(dirBlock);
printf("%d\t%d\n",myTable->dirUnitAmount, unitTemp.startBlock);
}
}
}
//切換目錄 cd
int changeDir(char dirName[])
{
//目錄項在目錄位置
int unitIndex = findUnitInTable(currentDirTable, dirName);
//不存在
if(unitIndex == -1)
{
printf("file not found\n");
return -1;
}
if(currentDirTable->dirs[unitIndex].type == 1)
{
printf("not a dir\n");
return -1;
}
//修改當前目錄
int dirBlock = currentDirTable->dirs[unitIndex].startBlock;
currentDirTable = (dirTable*)getBlockAddr(dirBlock);
//修改全域性絕對路徑
if(strcmp(dirName, "..") == 0)
{
//回退絕對路徑
int len = strlen(path);
for(int i=len-2;i>=0;i--)
if(path[i] == '\\')
{
path[i+1]='\0';
break;
}
}else {
strcat(path, dirName);
strcat(path, "\\");
}
return 0;
}
//修改檔名或者目錄名 mv
int changeName(char oldName[], char newName[])
{
int unitIndex = findUnitInTable(currentDirTable, oldName);
if(unitIndex == -1)
{
printf("file not found\n");
return -1;
}
strcpy(currentDirTable->dirs[unitIndex].fileName, newName);
return 0;
}
//******************建立和刪除檔案
//建立檔案 touch
int creatFile(char fileName[], int fileSize)
{
//檢測檔名字長度
if(strlen(fileName) >= 59)
{
printf("file name too long\n");
return -1;
}
//獲得FCB的空間
int FCBBlock = getBlock(1);
if(FCBBlock == -1)
return -1;
//獲取檔案資料空間
int FileBlock = getBlock(fileSize);
if(FileBlock == -1)
return -1;
//建立FCB
if(creatFCB(FCBBlock, FileBlock, fileSize) == -1)
return -1;
//新增到目錄項
if(addDirUnit(currentDirTable, fileName, 1, FCBBlock) == -1)
return -1;
return 0;
}
//建立目錄 mkdir
int creatDir(char dirName[])
{
if(strlen(dirName) >= 59)
{
printf("file name too long\n");
return -1;
}
//為目錄表分配空間
int dirBlock = getBlock(1);
if(dirBlock == -1)
return -1;
//將目錄作為目錄項新增到當前目錄
if(addDirUnit(currentDirTable, dirName, 0, dirBlock) == -1)
return -1;
//為新建的目錄新增一個到父目錄的目錄項
dirTable* newTable = (dirTable*)getBlockAddr(dirBlock);
newTable->dirUnitAmount = 0;
char parent[] = "..";
if(addDirUnit(newTable, parent, 0, getAddrBlock((char*)currentDirTable)) == -1)
return -1;
return 0;
}
//建立FCB
int creatFCB(int fcbBlockNum, int fileBlockNum, int fileSize)
{
//找到fcb的儲存位置
FCB* currentFCB = (FCB*) getBlockAddr(fcbBlockNum);
currentFCB->blockNum = fileBlockNum;//檔案資料起始位置
currentFCB->fileSize = fileSize;//檔案大小
currentFCB->link = 1;//檔案連結數
currentFCB->dataSize = 0;//檔案已寫入資料長度
currentFCB->readptr = 0;//檔案讀指標
return 0;
}
//新增目錄項
int addDirUnit(dirTable* myDirTable, char fileName[], int type, int FCBBlockNum)
{
//獲得目錄表
int dirUnitAmount = myDirTable->dirUnitAmount;
//檢測目錄表示是否已滿
if(dirUnitAmount == dirTable_max_size)
{
printf("dirTables is full, try to delete some file\n");
return -1;
}
//是否存在同名檔案
if(findUnitInTable(myDirTable, fileName) != -1)
{
printf("file already exist\n");
return -1;
}
//構建新目錄項
dirUnit* newDirUnit = &myDirTable->dirs[dirUnitAmount];
myDirTable->dirUnitAmount++;//當前目錄表的目錄項數量+1
//設定新目錄項內容
strcpy(newDirUnit->fileName, fileName);
newDirUnit->type = type;
newDirUnit->startBlock = FCBBlockNum;
return 0;
}
//刪除檔案 rm
int deleteFile(char fileName[])
{
//忽略系統的自動建立的父目錄
if(strcmp(fileName, "..") == 0)
{
printf("can't delete ..\n");
return -1;
}
//查詢檔案的目錄項位置
int unitIndex = findUnitInTable(currentDirTable, fileName);
if(unitIndex == -1)
{
printf("file not found\n");
return -1;
}
dirUnit myUnit = currentDirTable->dirs[unitIndex];
//判斷型別
if(myUnit.type == 0)//目錄
{
printf("not a file\n");
return -1;
}
int FCBBlock = myUnit.startBlock;
//釋放記憶體
releaseFile(FCBBlock);
//從目錄表中剔除
deleteDirUnit(currentDirTable, unitIndex);
return 0;
}
//釋放檔案記憶體
int releaseFile(int FCBBlock)
{
FCB* myFCB = (FCB*)getBlockAddr(FCBBlock);
myFCB->link--; //連結數減一
//無連結,刪除檔案
if(myFCB->link == 0)
{
//釋放檔案的資料空間
releaseBlock(myFCB->blockNum, myFCB->fileSize);
}
//釋放FCB的空間
releaseBlock(FCBBlock, 1);
return 0;
}
//刪除目錄項
int deleteDirUnit(dirTable* myDirTable, int unitIndex)
{
//遷移覆蓋
int dirUnitAmount = myDirTable->dirUnitAmount;
for(int i=unitIndex; i<dirUnitAmount-1; i++)
{
myDirTable->dirs[i] = myDirTable->dirs[i+1];
}
myDirTable->dirUnitAmount--;
return 0;
}
//刪除目錄 rmdir
int deleteDir(char dirName[])
{
//忽略系統的自動建立的父目錄
if(strcmp(dirName, "..") == 0)
{
printf("can't delete ..\n");
return -1;
}
//查詢檔案
int unitIndex = findUnitInTable(currentDirTable, dirName);
if(unitIndex == -1)
{
printf("file not found\n");
return -1;
}
dirUnit myUnit = currentDirTable->dirs[unitIndex];
//判斷型別
if(myUnit.type == 0)//目錄
{
deleteFileInTable(currentDirTable, unitIndex);
}else {
printf("not a dir\n");
return -1;
}
//從目錄表中剔除
deleteDirUnit(currentDirTable, unitIndex);
return 0;
}
//刪除檔案/目錄項
int deleteFileInTable(dirTable* myDirTable, int unitIndex)
{
//查詢檔案
dirUnit myUnit = myDirTable->dirs[unitIndex];
//判斷型別
if(myUnit.type == 0)//目錄
{
//找到目錄位置
int FCBBlock = myUnit.startBlock;
dirTable* table = (dirTable*)getBlockAddr(FCBBlock);
//遞迴刪除目錄下的所有檔案
printf("cycle delete dir %s\n", myUnit.fileName);
int unitCount = table->dirUnitAmount;
for(int i=1; i<unitCount; i++)//忽略“..”
{
printf("delete %s\n", table->dirs[i].fileName);
deleteFileInTable(table, i);
}
//釋放目錄表空間
releaseBlock(FCBBlock, 1);
}else {//檔案
//釋放檔案記憶體
int FCBBlock = myUnit.startBlock;
releaseFile(FCBBlock);
}
return 0;
}
//**********************讀寫操作
//讀檔案 read
int read(char fileName[], int length)
{
int unitIndex = findUnitInTable(currentDirTable, fileName);
if(unitIndex == -1)
{
printf("file no found\n");
return -1;
}
//控制塊
int FCBBlock = currentDirTable->dirs[unitIndex].startBlock;
FCB* myFCB = (FCB*)getBlockAddr(FCBBlock);
doRead(myFCB, length);
return 0;
}
//重新讀檔案 reread
int reread(char fileName[], int length)
{
int unitIndex = findUnitInTable(currentDirTable, fileName);
if(unitIndex == -1)
{
printf("file no found\n");
return -1;
}
//控制塊
int FCBBlock = currentDirTable->dirs[unitIndex].startBlock;
FCB* myFCB = (FCB*)getBlockAddr(FCBBlock);
myFCB->readptr = 0;
doRead(myFCB, length);
return 0;
}
//執行讀操作
int doRead(FCB* myFCB, int length)
{
//讀資料
int dataSize = myFCB->dataSize;
char* data = (char*)getBlockAddr(myFCB->blockNum);
//在不超出資料長度下,讀取指定長度的資料
for(int i=0; i<length && myFCB->readptr < dataSize; i++, myFCB->readptr++)
{
printf("%c", *(data+myFCB->readptr));
}
if(myFCB->readptr == dataSize)//讀到檔案末尾用#表示
printf("#");
//換行美觀
printf("\n");
return 0;
}
//寫檔案,從末尾寫入 write
int write(char fileName[], char content[])
{
int unitIndex = findUnitInTable(currentDirTable, fileName);
if(unitIndex == -1)
{
printf("file no found\n");
return -1;
}
//控制塊
int FCBBlock = currentDirTable->dirs[unitIndex].startBlock;
FCB* myFCB = (FCB*)getBlockAddr(FCBBlock);
doWrite(myFCB, content);
return 0;
}
//重新寫覆蓋 rewrite
int rewrite(char fileName[], char content[])
{
int unitIndex = findUnitInTable(currentDirTable, fileName);
if(unitIndex == -1)
{
printf("file no found\n");
return -1;
}
//控制塊
int FCBBlock = currentDirTable->dirs[unitIndex].startBlock;
FCB* myFCB = (FCB*)getBlockAddr(FCBBlock);
//重設資料塊
myFCB->dataSize = 0;
myFCB->readptr = 0;
doWrite(myFCB, content);
return 0;
}
//執行寫操作
int doWrite(FCB* myFCB, char content[])
{
int contentLen = strlen(content);
int fileSize = myFCB->fileSize * block_szie;
char* data = (char*)getBlockAddr(myFCB->blockNum);
//在不超出檔案的大小的範圍內寫入
for(int i=0; i<contentLen && myFCB->dataSize<fileSize; i++, myFCB->dataSize++)
{
*(data+myFCB->dataSize) = content[i];
}
if(myFCB->dataSize == fileSize)
printf("file is full,can't write in\n");
return 0;
}
//從目錄中查詢目錄專案
int findUnitInTable(dirTable* myDirTable, char unitName[])
{
//獲得目錄表
int dirUnitAmount = myDirTable->dirUnitAmount;
int unitIndex = -1;
for(int i=0; i<dirUnitAmount; i++)//查詢目錄項位置
if(strcmp(unitName, myDirTable->dirs[i].fileName) == 0)
unitIndex = i;
return unitIndex;
}
工程程式碼連結(含有exe可直接執行):FileSystem