生活随笔
收集整理的這篇文章主要介紹了
FAT16图文详解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
注:FAT16驅動代碼不是本人編寫的,是從網上下載的,本人只是對該代碼進行研讀學習,并做下筆記。該FAT16驅動應該是比較老的了,猜測應該在DOS時代比較流行,但放在今天,對于剛剛進階FAT16的小伙伴來說,還是很適合初學者學習的好資料!筆者也相信,只要小伙伴們靜下心來,慢慢讀懂該代碼,相信很快就能在腦海中形成一張FAT16的總覽圖了。
??????? 筆者對代碼進行了簡單測試,在STM32平臺上對2G SD卡進行了讀寫TXT操作,沒有問題。當然,這個代碼功能還是很簡單的,只有創建、讀、寫文件3個操作,而且寫操作不能修改文件的大小,即沒有追加功能,文件的大小是由CreateFile一開始創建好了的。
?
以下為源碼部分:
[cpp] view plaincopyprint?
??????????#include?"stm32f10x.h" ??#include?"fat16.h" ??#include?"sd.h" ????????u16?BytesPerSector;??u16?ResvdSectors;??u16?RootDirCnt;??u16?SectorsPerFAT;??u16?DirStartSector;??u16?DataStartSector;??u16?DBRStartSector;??u8?SectorsPerClus;??u8?FATCount;??u8?SectorBuf[512];??????static?u8?ReadBlock(u16?LBA)??{??????return?SD_ReadSector(SectorBuf,?LBA?+?DBRStartSector,?1);??}??????static?u8?WriteBlock(u16?LBA)??{??????return?SD_WriteSector(SectorBuf,?LBA?+?DBRStartSector,?1);??}??????static?void?NameFormat(const?char*?SrcName,?char*?DstName)??{??????u8?i,?j;??????????????for(i?=?0;?i?<?11;?i++)??????????*(DstName?+?i)?=?0x20;??????????????for(i?=?0,?j?=?0;?i?<?8;?i++,?j++)??????{??????????if((*SrcName)?==?'.')???????????????{??????????????SrcName++;??????????????break;??????????}??????????else??????????{??????????????*(DstName?+?j)?=?*SrcName++;??????????}??????}??????????????for(i?=?0,?j?=?8;?i?<?3;?i++,?j++)??????{??????????if((*SrcName)?==?0)???break;??????????else??????????????{??????????????*(DstName?+?j)?=?*SrcName++;??????????}??????}??}??????static?u8?IsEqual(void*?Src1,?void*?Src2,?u32?size)??{??????u8?*p1,?*p2;????????p1?=?Src1;??????p2?=?Src2;??????for(;?size--;?)??????{??????????if((*p1++)?!=?(*p2++))??????????????return?0;????????}??????return?1;??}??????static?u16?Clus2Sector(u16?clus)??{??????return?(DataStartSector?+?((clus?-?2)?*?SectorsPerClus));??}??????static?u8?ReadMBR(void)??{??????tMBR?*pmbr?=?(tMBR?*)SectorBuf;???????? ??????if(0?==?ReadBlock(0))???return?0;??????if(0xAA55?!=?pmbr->Flag)?return?0;?????? ??????DBRStartSector?=?(pmbr->DPT[0].LBAoffest[1]?<<?16)?+?pmbr->DPT[0].LBAoffest[0];?????????return?1;??}??????static?u8?ReadDBR(void)??{??????tDBR?*pdbr?=?(tDBR*)SectorBuf;????????if(0?==?ReadBlock(0))?return?0;??????if(0xAA55?!=?pdbr->Flag)?return?0;??????????????BytesPerSector?=?(pdbr->BPB.BytesPerSector[1]?<<?8)?+?pdbr->BPB.BytesPerSector[0];??????SectorsPerClus?=?pdbr->BPB.SectorsPerClus;??????ResvdSectors?=?(pdbr->BPB.ResvdSectors[1]?<<?8)?+?pdbr->BPB.ResvdSectors[0];??????FATCount?=?pdbr->BPB.FATCount;??????RootDirCnt?=?(pdbr->BPB.DirCount[1]?<<?8)?+?pdbr->BPB.DirCount[0];??????SectorsPerFAT?=?(pdbr->BPB.SectorsPerFAT[1]?<<?8)?+?pdbr->BPB.SectorsPerFAT[0];??????DirStartSector?=?ResvdSectors?+?SectorsPerFAT?*?FATCount;??????DataStartSector?=?DirStartSector?+?32;????????return?1;??}??????static?u16?ReadFAT(u16?Index)??{??????u16?*pItem?=?(u16*)&SectorBuf[0];??????????????if(0?==?ReadBlock((Index?>>?8)?+?ResvdSectors))?return?0;????????????return?*(pItem?+?(Index?%?256));??}??????static?u16?WriteFAT(u16?Index,?u16?val)??{??????u16?*pItem?=?(u16*)&SectorBuf[0];????????????u16?sector?=?(Index?>>?8)?+?ResvdSectors;????????if(0?==?ReadBlock(sector))?return?0;????????????*(pItem?+?(Index?%?256))?=?val;??????if(0?==?WriteBlock(sector))?return?0;??????return?1;??}????????static?u8?CopyFAT(u16?sector)??{??????if(!ReadBlock(ResvdSectors?+?sector))?return?0;??????if(!WriteBlock(ResvdSectors?+?SectorsPerFAT?+?sector))?return?0;??????return?1;??}??????u8?FAT_Init(void)??{????????????if(0?==?ReadMBR())?return?0;????????????if(0?==?ReadDBR())?return?0;????????return?1;?????}??????u8?GetFileDir(const?char*?name,?tDIR?*dir)??{??????u8?i,?j;??????tDIR?*pDir;??????char?DOSname[11];??????????????NameFormat(name,?DOSname);??????????????for(j?=?0;?j?<?32;?j++)??????{??????????if(0?==?ReadBlock(DirStartSector?+?j))?return?0;????????????????????for(i?=?0;?i?<?16;?i++)??????????{?????????????? ??????????????pDir?=?(tDIR?*)&SectorBuf[i?<<?5];????????????????????????????if(IsEqual(DOSname,?pDir->Name,?11))??????????????{??????????????????*dir?=?*pDir;??????????????????return?1;?????????????????}??????????}??????}??????return?0;??}??????static?u8?WriteDir(u16?Index,?tDIR?*dir)??{??????tDIR?*pDir;????????????u16?sector?=?Index?/?16?+?DirStartSector;????????if(!ReadBlock(sector))?return?0;??????pDir?=?(tDIR*)&SectorBuf[0];????????????*(pDir?+?(Index?%?16))?=?*dir;??????if(!WriteBlock(sector))?return?0;????????return?1;??}??????static?u16?GetEmptyDir(void)??{??????u8?j,?i;??????u16?index?=?0;??????????????for(i?=?0;?i?<?32;?i++)??????{??????????if(!ReadBlock(DirStartSector?+?i))?return?0xffff;????????????????????for(j?=?0;?j?<?16;?j++)??????????{?????????????? ??????????????if(0?==?SectorBuf[j?*?32])??????????????????return?index;??????????????index++;??????????????}??????}????????return?0xffff;??}??????static?u16?GetEmptyFAT(void)??{??????u16?i,?j;??????u16?*pItem;??????????????for(i?=?0;?i?<?SectorsPerFAT;?i++)??????{??????????if(0?==?ReadBlock(i?+?ResvdSectors))?return?0;??????????pItem?=?(u16*)&SectorBuf[0];????????????????????for(j?=?0;?j?<?256;?j++)??????????{??????????????if(*(pItem?+?j)?==?0)?return?((i?<<?8)?+?j);??????????}??????}??????return?0;??}????????????u8?CreateFile(const?char*?name,?u32?size)??{??????tDIR?dir?=?{0};? ??????u16?ClusID;??????u16?i;??????u16?FATSector;????????????u32?BytesPerClus?=?BytesPerSector?*?SectorsPerClus;??????????????if(GetFileDir(name,?&dir))?return?0;??????????????i?=?GetEmptyDir();??????if(i?==?0xffff)?return?0;??????????????ClusID?=?GetEmptyFAT();?????? ??????if(0?==?WriteFAT(ClusID,?0xFFFF))?return?0;??????????????NameFormat(name,?dir.Name);??????dir.Attri?=?0;??????dir.FirstClus?=?ClusID;??????dir.Length[0]?=?size;??????dir.Length[1]?=?size?>>?16;????????????if(0?==?WriteDir(i,?&dir))?return?0;??????????????FATSector?=?ClusID?/?256;??????for(/*文件所占簇個數*/i?=?size?/?BytesPerClus;?i?!=?0;?i--)??????{??????????u16?NextClus;??????????????????????NextClus?=?GetEmptyFAT();??????????if(!NextClus)?return?0;????????????????????if(0?==?WriteFAT(ClusID,?NextClus))?return?0;??????????if(0?==?WriteFAT(NextClus,?0xFFFF))?return?0;????????????????????if(FATSector?!=?(NextClus?/?256))??????????{??????????????CopyFAT(FATSector);????????????????????????????FATSector?=?NextClus?/?256;??????????}??????????ClusID?=?NextClus;??????}????????????CopyFAT(FATSector);????????return?1;??}?????????????????????u8?ReadFile(const?char*?name,?u32?offest,?void*?dst,?u32?len)??{??????tDIR?dir;??????u16?ClusID;??????u16?StartSector;??????u32?FileSize;??????u32?PtrByteOffest,?PtrSectorOffest,?PtrClusOffest;??????u16?i;??????u8?*pDst?=?(u8*)dst;??????????????if(!GetFileDir(name,?&dir))?return?0;????????FileSize?=?(dir.Length[1]?<<?16)?+?dir.Length[0];????????????if(offest?>?FileSize)?return?0;????????????if((offest?+?len)?>?FileSize)??????????len?=?FileSize?-?offest;????????ClusID?=?dir.FirstClus;????????????PtrSectorOffest?=?offest?/?BytesPerSector;????????????PtrByteOffest?=?offest?%?BytesPerSector;????????????PtrClusOffest?=?PtrSectorOffest?/?SectorsPerClus;??????????????for(i?=?0;?i?<?PtrClusOffest;?i++)??????????ClusID?=?ReadFAT(ClusID);????????????StartSector?=?Clus2Sector(ClusID)?+?PtrSectorOffest;????????while(1)??????{????????????????????for(;?PtrSectorOffest?<?SectorsPerClus;?PtrSectorOffest++)??????????{??????????????if(!ReadBlock(StartSector++))?return?0;???????????????? ??????????????for(;?PtrByteOffest?<?BytesPerSector;?PtrByteOffest++)??????????????{??????????????????*pDst++?=?SectorBuf[PtrByteOffest];??????????????????len--;??????????????????if(0?==?len)?return?1;??????????????}??????????????PtrByteOffest?=?0;??????????}????????????????????ClusID?=?ReadFAT(ClusID);????????????????????StartSector?=?Clus2Sector(ClusID);??????????PtrSectorOffest?=?0;??????}??}??????u8?WriteFile(const?char*?name,?u32?offest,?void*?src,?u32?len)??{??????tDIR?dir;??????u16?ClusID;??????u16?StartSector;??????u32?FileSize;??????u32?PtrByteOffest,?PtrSectorOffest,?PtrClusOffest;??????u16?i;??????u8?*pSrc?=?(u8*)src;????????if(!GetFileDir(name,?&dir))?return?0;????????FileSize?=?(dir.Length[1]?<<?16)?+?dir.Length[0];????????????if(offest?>?FileSize)?return?0;????????????if((offest?+?len)?>?FileSize)??????????len?=?FileSize?-?offest;????????ClusID?=?dir.FirstClus;????????????PtrSectorOffest?=?offest?/?BytesPerSector;????????????PtrByteOffest?=?offest?%?BytesPerSector;????????????PtrClusOffest?=?PtrSectorOffest?/?SectorsPerClus;??????????????for(i?=?0;?i?<?PtrClusOffest;?i++)??????????ClusID?=?ReadFAT(ClusID);????????????StartSector?=?Clus2Sector(ClusID)?+?PtrSectorOffest;????????while(1)??????{????????????????????for(;?PtrSectorOffest?<?SectorsPerClus;?PtrSectorOffest++)??????????{??????????????if(!ReadBlock(StartSector))?return?0;???????????????? ??????????????for(;?PtrByteOffest?<?BytesPerSector;?PtrByteOffest++)??????????????{??????????????????SectorBuf[PtrByteOffest]?=?*pSrc++;??????????????????len--;??????????????????if(0?==?len)??????????????????{??????????????????????if(!WriteBlock(StartSector))?return?0;??????????????????????else?return?1;??????????????????}??????????????}??????????????if(!WriteBlock(StartSector++))?return?0;??????????????PtrByteOffest?=?0;??????????}????????????????????ClusID?=?ReadFAT(ClusID);????????????????????StartSector?=?Clus2Sector(ClusID);??????????PtrSectorOffest?=?0;??????}??}?? //****************************************************************************************************
//文件名:FAT16.c
//來源:網絡
//注釋:hexiaolong2009(http://blog.csdn.net/hexiaolong2009)
//****************************************************************************************************
#include "stm32f10x.h"
#include "fat16.h"
#include "sd.h"//****************************************************************************************************
//全局變量定義
u16 BytesPerSector;
u16 ResvdSectors;
u16 RootDirCnt;
u16 SectorsPerFAT;
u16 DirStartSector;
u16 DataStartSector;
u16 DBRStartSector;
u8 SectorsPerClus;
u8 FATCount;
u8 SectorBuf[512];//讀取一個邏輯扇區
static u8 ReadBlock(u16 LBA)
{return SD_ReadSector(SectorBuf, LBA + DBRStartSector, 1);
}//寫入一個邏輯扇區
static u8 WriteBlock(u16 LBA)
{return SD_WriteSector(SectorBuf, LBA + DBRStartSector, 1);
}//將文件名格式化成標準的DOS 8.3格式的文件名
static void NameFormat(const char* SrcName, char* DstName)
{u8 i, j;//首先用空格初始化目標緩沖區for(i = 0; i < 11; i++)*(DstName + i) = 0x20;//其次拷貝文件名for(i = 0, j = 0; i < 8; i++, j++){if((*SrcName) == '.') {SrcName++;break;}else{*(DstName + j) = *SrcName++;}}//最后拷貝擴展名for(i = 0, j = 8; i < 3; i++, j++){if((*SrcName) == 0) break;else {*(DstName + j) = *SrcName++;}}
}//比較兩個緩沖區的前size個字節是否完全相同
static u8 IsEqual(void* Src1, void* Src2, u32 size)
{u8 *p1, *p2;p1 = Src1;p2 = Src2;for(; size--; ){if((*p1++) != (*p2++))return 0;}return 1;
}//將簇號轉換為邏輯扇區號
static u16 Clus2Sector(u16 clus)
{return (DataStartSector + ((clus - 2) * SectorsPerClus));
}//讀取主引導記錄MBR
static u8 ReadMBR(void)
{tMBR *pmbr = (tMBR *)SectorBuf;//因為此時的DBRStartSector還未被賦值,等于0,所以這里讀取的是物理扇區0if(0 == ReadBlock(0)) return 0;if(0xAA55 != pmbr->Flag) return 0;//通過磁盤分區表DPT字段來獲取系統引導扇區DBR的扇區偏移量DBRStartSector = (pmbr->DPT[0].LBAoffest[1] << 16) + pmbr->DPT[0].LBAoffest[0]; return 1;
}//讀取系統引導扇區DBR
static u8 ReadDBR(void)
{tDBR *pdbr = (tDBR*)SectorBuf;if(0 == ReadBlock(0)) return 0;if(0xAA55 != pdbr->Flag) return 0;//通過系統引導扇區中的BPB字段,計算磁盤的相關參數BytesPerSector = (pdbr->BPB.BytesPerSector[1] << 8) + pdbr->BPB.BytesPerSector[0];SectorsPerClus = pdbr->BPB.SectorsPerClus;ResvdSectors = (pdbr->BPB.ResvdSectors[1] << 8) + pdbr->BPB.ResvdSectors[0];FATCount = pdbr->BPB.FATCount;RootDirCnt = (pdbr->BPB.DirCount[1] << 8) + pdbr->BPB.DirCount[0];SectorsPerFAT = (pdbr->BPB.SectorsPerFAT[1] << 8) + pdbr->BPB.SectorsPerFAT[0];DirStartSector = ResvdSectors + SectorsPerFAT * FATCount;DataStartSector = DirStartSector + 32;return 1;
}//讀取FAT表項的值
static u16 ReadFAT(u16 Index)
{u16 *pItem = (u16*)&SectorBuf[0];//因為1扇區 = 256個FAT表項,所以Index >> 8表示從FAT開始的扇區偏移if(0 == ReadBlock((Index >> 8) + ResvdSectors)) return 0;//Index % 256 表示扇區內的字偏移return *(pItem + (Index % 256));
}//寫入某一FAT表項的值
static u16 WriteFAT(u16 Index, u16 val)
{u16 *pItem = (u16*)&SectorBuf[0];//計算Index所在的邏輯扇區號u16 sector = (Index >> 8) + ResvdSectors;if(0 == ReadBlock(sector)) return 0;//Index % 256 表示扇區內的字偏移*(pItem + (Index % 256)) = val;if(0 == WriteBlock(sector)) return 0;return 1;
}//將FAT1的某一扇區拷貝到FAT2所對應的扇區
//sector表示從FAT1開始的扇區偏移
static u8 CopyFAT(u16 sector)
{if(!ReadBlock(ResvdSectors + sector)) return 0;if(!WriteBlock(ResvdSectors + SectorsPerFAT + sector)) return 0;return 1;
}//FAT16初始化
u8 FAT_Init(void)
{//先讀取MBR,找到系統引導扇區的位置if(0 == ReadMBR()) return 0;//再讀取系統引導扇區中的BPB,獲取磁盤的相關參數if(0 == ReadDBR()) return 0;return 1;
}//查找根目錄下是否存在name所對應的文件,如果存在則將該文件信息存放到dir所指向的結構體中
u8 GetFileDir(const char* name, tDIR *dir)
{u8 i, j;tDIR *pDir;char DOSname[11];//第一步要將name格式化成標準8.3格式的文件名NameFormat(name, DOSname);//因為根目錄區總共占32個扇區for(j = 0; j < 32; j++){if(0 == ReadBlock(DirStartSector + j)) return 0;//而每個扇區又包含16個目錄項for(i = 0; i < 16; i++){//每個目錄項又占32個字節,所以這里用i << 5表示目錄項在一個扇區中的字節偏移pDir = (tDIR *)&SectorBuf[i << 5];//通過文件名來查找文件if(IsEqual(DOSname, pDir->Name, 11)){*dir = *pDir;return 1; }}}return 0;
}//將文件信息寫入Index所指定的目錄項中
static u8 WriteDir(u16 Index, tDIR *dir)
{tDIR *pDir;//計算Index所在的邏輯扇區偏移,Index / 16表示從目錄區開始的扇區偏移量u16 sector = Index / 16 + DirStartSector;if(!ReadBlock(sector)) return 0;pDir = (tDIR*)&SectorBuf[0];//Index % 16表示1個扇區內的目錄項偏移*(pDir + (Index % 16)) = *dir;if(!WriteBlock(sector)) return 0;return 1;
}//從根目錄區中獲取一個空的目錄項
static u16 GetEmptyDir(void)
{u8 j, i;u16 index = 0;//因為根目錄區總共占32個扇區for(i = 0; i < 32; i++){if(!ReadBlock(DirStartSector + i)) return 0xffff;//而每個扇區又包含16個目錄項for(j = 0; j < 16; j++){//每個目錄項又占32個字節,所以這里用j * 32表示目錄項在一個扇區中的字節偏移if(0 == SectorBuf[j * 32])return index;index++; }}return 0xffff;
}//獲取一個空的FAT表項,即一個空簇的簇號
static u16 GetEmptyFAT(void)
{u16 i, j;u16 *pItem;//遍歷FAT表所占的每個扇區for(i = 0; i < SectorsPerFAT; i++){if(0 == ReadBlock(i + ResvdSectors)) return 0;pItem = (u16*)&SectorBuf[0];//遍歷扇區內的每個FAT表項for(j = 0; j < 256; j++){if(*(pItem + j) == 0) return ((i << 8) + j);}}return 0;
}//新建一個文件
//注意:文件的大小已固定為size字節,即使新建的文件沒有寫任何內容,文件的大小始終為size大小;
// 即使對該文件寫入了超過size大小的內容,文件的大小依然不改變
//該函數有待進一步優化,對于大文件的創建,該函數速度非常緩慢
u8 CreateFile(const char* name, u32 size)
{tDIR dir = {0}; //一定要初始化為0,否則在WINDOWS系統下無法識別文件u16 ClusID;u16 i;u16 FATSector;//計算一簇所占的字節數u32 BytesPerClus = BytesPerSector * SectorsPerClus;//文件已存在,則返回if(GetFileDir(name, &dir)) return 0;//首先從根目錄區獲取一個空的目錄項i = GetEmptyDir();if(i == 0xffff) return 0;//從FAT表中獲取一個空的FAT表項ClusID = GetEmptyFAT();//立即將該空的FAT表項填充為0xFFFF,以免后面再次獲取空的FAT表項時錯誤的分配到同一表項if(0 == WriteFAT(ClusID, 0xFFFF)) return 0;//然后給該目錄項填充文件信息NameFormat(name, dir.Name);dir.Attri = 0;dir.FirstClus = ClusID;dir.Length[0] = size;dir.Length[1] = size >> 16;//將目錄信息回寫到目錄表中if(0 == WriteDir(i, &dir)) return 0;//計算分配到的FAT表項在FAT表中的扇區偏移FATSector = ClusID / 256;for(/*文件所占簇個數*/i = size / BytesPerClus; i != 0; i--){u16 NextClus;//獲取下一個空簇的簇號NextClus = GetEmptyFAT();if(!NextClus) return 0;//此部分有待優化if(0 == WriteFAT(ClusID, NextClus)) return 0;if(0 == WriteFAT(NextClus, 0xFFFF)) return 0;//當下一FAT表項所在位置不在當前FAT扇區時,立即將當前FAT1扇區的內容拷貝到對應的FAT2中if(FATSector != (NextClus / 256)){CopyFAT(FATSector);//并將下一FAT表項所在扇區偏移賦值給FATSectorFATSector = NextClus / 256;}ClusID = NextClus;}//將最后一扇區拷貝到FAT2中的相應位置CopyFAT(FATSector);return 1;
} //讀取文件
u8 ReadFile(const char* name, u32 offest, void* dst, u32 len)
{tDIR dir;u16 ClusID;u16 StartSector;u32 FileSize;u32 PtrByteOffest, PtrSectorOffest, PtrClusOffest;u16 i;u8 *pDst = (u8*)dst;//首先找到文件對應的目錄項if(!GetFileDir(name, &dir)) return 0;FileSize = (dir.Length[1] << 16) + dir.Length[0];//文件指針超出文件尾則返回if(offest > FileSize) return 0;//len大于文件長度的情況if((offest + len) > FileSize)len = FileSize - offest;ClusID = dir.FirstClus;//文件指針相對于文件頭的扇區偏移PtrSectorOffest = offest / BytesPerSector;//文件指針相對于當前扇區的字節偏移PtrByteOffest = offest % BytesPerSector;//文件指針相對于文件頭的簇偏移PtrClusOffest = PtrSectorOffest / SectorsPerClus;//找到文件指針所在簇號for(i = 0; i < PtrClusOffest; i++)ClusID = ReadFAT(ClusID);//文件指針相對于系統分區的扇區偏移StartSector = Clus2Sector(ClusID) + PtrSectorOffest;while(1){//2.從指針所在的扇區開始,遍歷文件的每個扇區for(; PtrSectorOffest < SectorsPerClus; PtrSectorOffest++){if(!ReadBlock(StartSector++)) return 0;//1.從指針所在扇區的字節偏移開始,遍歷扇區的每個字節for(; PtrByteOffest < BytesPerSector; PtrByteOffest++){*pDst++ = SectorBuf[PtrByteOffest];len--;if(0 == len) return 1;}PtrByteOffest = 0;}//讀取下一簇號ClusID = ReadFAT(ClusID);//獲取下一簇所在的扇區號StartSector = Clus2Sector(ClusID);PtrSectorOffest = 0;}
}//寫文件
u8 WriteFile(const char* name, u32 offest, void* src, u32 len)
{tDIR dir;u16 ClusID;u16 StartSector;u32 FileSize;u32 PtrByteOffest, PtrSectorOffest, PtrClusOffest;u16 i;u8 *pSrc = (u8*)src;if(!GetFileDir(name, &dir)) return 0;FileSize = (dir.Length[1] << 16) + dir.Length[0];//文件指針超出文件尾則返回if(offest > FileSize) return 0;//len大于文件長度的情況if((offest + len) > FileSize)len = FileSize - offest;ClusID = dir.FirstClus;//文件指針相對于文件頭的扇區偏移PtrSectorOffest = offest / BytesPerSector;//文件指針相對于當前扇區的字節偏移PtrByteOffest = offest % BytesPerSector;//文件指針相對于文件頭的簇偏移PtrClusOffest = PtrSectorOffest / SectorsPerClus;//找到文件指針所在簇號for(i = 0; i < PtrClusOffest; i++)ClusID = ReadFAT(ClusID);//文件指針相對于系統分區的扇區偏移StartSector = Clus2Sector(ClusID) + PtrSectorOffest;while(1){//2.從指針所在的扇區開始,遍歷文件的每個扇區for(; PtrSectorOffest < SectorsPerClus; PtrSectorOffest++){if(!ReadBlock(StartSector)) return 0;//1.從指針所在扇區的字節偏移開始,遍歷扇區的每個字節for(; PtrByteOffest < BytesPerSector; PtrByteOffest++){SectorBuf[PtrByteOffest] = *pSrc++;len--;if(0 == len){if(!WriteBlock(StartSector)) return 0;else return 1;}}if(!WriteBlock(StartSector++)) return 0;PtrByteOffest = 0;}//讀取下一簇號ClusID = ReadFAT(ClusID);//獲取下一簇所在的扇區號StartSector = Clus2Sector(ClusID);PtrSectorOffest = 0;}
}
?
?
?
?
?
?
?
源碼下載:??FAT16.zip?
圖文PDF下載:??FAT16模塊詳解.pdf?
轉自:http://blog.csdn.net/hexiaolong2009/article/details/17592583
總結
以上是生活随笔為你收集整理的FAT16图文详解的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。