在上一节中,我们成功的将虚拟软盘进行了格式化,而且将文件存入其中,那么如何在根目录区中查找文件呢?为了方便起见,再次给出FAT12文件系统的格式,如下所示:
在FAT12文件系统中,一簇包含一个扇区。从上图可见,目录文件项的偏移为19个扇区,其本身大小占用了14个扇区。根目录区中是一个一个的目录项,目录项的具体成员与分布如下所示:
每一个目录项代表根目录中一个文件的索引,其大小为32字节,根据目录项中文件开始的簇号和文件大小,我们可以找到文件的具体内容。下面我们先来读取一下FAT12文件系统根目录的信息,步骤如下:
1、创建RootEntry结构体类型
2、使用文件流顺序读取每个项的内容
3、解析并打印相关的信息
在Qt creater中编写程序如下:
1 #include <QtCore/QCoreApplication> 2 #include <QFile> 3 #include <QDataStream> 4 #include <QDebug> 5 #include <QVector> 6 #include <QByteArray> 7 8 #pragma pack(push) 9 #pragma pack(1) 10 11 struct Fat12Header 12 { 13 char BS_OEMName[8]; 14 ushort BPB_BytsPerSec; 15 uchar BPB_SecPerClus; 16 ushort BPB_RsvdSecCnt; 17 uchar BPB_NumFATs; 18 ushort BPB_RootEntCnt; 19 ushort BPB_TotSec16; 20 uchar BPB_Media; 21 ushort BPB_FATSz16; 22 ushort BPB_SecPerTrk; 23 ushort BPB_NumHeads; 24 uint BPB_HiddSec; 25 uint BPB_TotSec32; 26 uchar BS_DrvNum; 27 uchar BS_Reserved1; 28 uchar BS_BootSig; 29 uint BS_VolID; 30 char BS_VolLab[11]; 31 char BS_FileSysType[8]; 32 }; 33 34 struct RootEntry 35 { 36 char DIR_Name[11]; 37 uchar DIR_Attr; 38 uchar reserve[10]; 39 ushort DIR_WrtTime; 40 ushort DIR_WrtDate; 41 ushort DIR_FstClus; 42 uint DIR_FileSize; 43 }; 44 45 #pragma pack(pop) 46 47 void PrintHeader(Fat12Header& rf, QString p) 48 { 49 QFile file(p); 50 51 if( file.open(QIODevice::ReadOnly) ) 52 { 53 QDataStream in(&file); 54 55 file.seek(3); 56 57 in.readRawData(reinterpret_cast<char*>(&rf), sizeof(rf)); 58 59 rf.BS_OEMName[7] = 0; 60 rf.BS_VolLab[10] = 0; 61 rf.BS_FileSysType[7] = 0; 62 63 qDebug() << "BS_OEMName: " << rf.BS_OEMName; 64 qDebug() << "BPB_BytsPerSec: " << hex << rf.BPB_BytsPerSec; 65 qDebug() << "BPB_SecPerClus: " << hex << rf.BPB_SecPerClus; 66 qDebug() << "BPB_RsvdSecCnt: " << hex << rf.BPB_RsvdSecCnt; 67 qDebug() << "BPB_NumFATs: " << hex << rf.BPB_NumFATs; 68 qDebug() << "BPB_RootEntCnt: " << hex << rf.BPB_RootEntCnt; 69 qDebug() << "BPB_TotSec16: " << hex << rf.BPB_TotSec16; 70 qDebug() << "BPB_Media: " << hex << rf.BPB_Media; 71 qDebug() << "BPB_FATSz16: " << hex << rf.BPB_FATSz16; 72 qDebug() << "BPB_SecPerTrk: " << hex << rf.BPB_SecPerTrk; 73 qDebug() << "BPB_NumHeads: " << hex << rf.BPB_NumHeads; 74 qDebug() << "BPB_HiddSec: " << hex << rf.BPB_HiddSec; 75 qDebug() << "BPB_TotSec32: " << hex << rf.BPB_TotSec32; 76 qDebug() << "BS_DrvNum: " << hex << rf.BS_DrvNum; 77 qDebug() << "BS_Reserved1: " << hex << rf.BS_Reserved1; 78 qDebug() << "BS_BootSig: " << hex << rf.BS_BootSig; 79 qDebug() << "BS_VolID: " << hex << rf.BS_VolID; 80 qDebug() << "BS_VolLab: " << rf.BS_VolLab; 81 qDebug() << "BS_FileSysType: " << rf.BS_FileSysType; 82 83 file.seek(510); 84 85 uchar b510 = 0; 86 uchar b511 = 0; 87 88 in.readRawData(reinterpret_cast<char*>(&b510), sizeof(b510)); 89 in.readRawData(reinterpret_cast<char*>(&b511), sizeof(b511)); 90 91 qDebug() << "Byte 510: " << hex << b510; 92 qDebug() << "Byte 511: " << hex << b511; 93 } 94 95 file.close(); 96 } 97 98 RootEntry FindRootEntry(Fat12Header& rf, QString p, int i) 99 { 100 RootEntry ret = {{0}}; 101 102 QFile file(p); 103 104 if( file.open(QIODevice::ReadOnly) && (0 <= i) && (i < rf.BPB_RootEntCnt) ) 105 { 106 QDataStream in(&file); 107 108 file.seek(19 * rf.BPB_BytsPerSec + i * sizeof(RootEntry)); 109 110 in.readRawData(reinterpret_cast<char*>(&ret), sizeof(ret)); 111 } 112 113 file.close(); 114 115 return ret; 116 } 117 156 void PrintRootEntry(Fat12Header& rf, QString p) 157 { 158 for(int i=0; i<rf.BPB_RootEntCnt; i++) 159 { 160 RootEntry re = FindRootEntry(rf, p, i); 161 162 if( re.DIR_Name[0] != '