JAVA——构建FAT32文件系统的FAT(File Allocation Table文件分配表)类
Maven<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency>
·
Maven
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
解决方案
package cn.edu.zstu.fms.storage;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* FAT表结构及作用
* 1、FAT32文件一般有两份FAT,他们由格式化程序在对分区进行格式化时创建,FAT1是主,FAT2是备份。
* 2、FAT1跟在DBR之后,其具体地址由DBR的BPB参数中指定,FAT2跟在FAT1的后面。
* 3、FAT表由FAT表项构成,我们把FAT表项简称FAT项,每个FAT项占用4字节。
* 4、每个FAT项都有一个固定的编号,这个编号从0开始。
* 5、FAT表项的前两个FAT项为文件系统保留使用,0号FAT为介质类型,1号FAT为文件系统错误标志。
* 6、分区的数据区中每个簇都会映射到FAT表中的唯一一个FAT项,因为0号FAT和1号FAT被系统占用,用户的数据从2号FAT开始记录。
* 7、如果某个文件占用很多个簇,则第一个FAT项记录下一个FAT项的编号(既簇号),如果这个文件结束了,则用“0F FF FF FF”表示。
* 8、分区格式化后,用户文件以簇为单位存放在数据区中,一个文件至少占用一个簇。
* 9、FAT的主要作用是标明分区存储的介质以及簇的使用情况。
* @see <a href="https://blog.51cto.com/dengqi/1349327">FAT32文件系统详解</a>
* @see <a href="https://blog.csdn.net/pnzrk/article/details/88943746">FAT32</a>
* @author ShenTuZhiGang
* @version 1.0.0
* @date 2020-12-16 22:42
*/
public class FileAllocationTable {
/**
* 源数据
*/
private byte[] source;
/**
* hash表
*/
private Map<Integer,Integer> table;
public FileAllocationTable(){
this(new byte[512*2]);
}
public FileAllocationTable(byte[] bytes){
table = new HashMap<>();
setSource(bytes);
}
public byte[] getSource() {
return source;
}
public void setSource(byte[] source) {
this.source = source;
for (int i=0; i<this.source.length; i+=4){
Integer item= getItem(i);
table.put(i/4,item);
}
}
private void setItem(int pos,Integer data) {
byte[] bytes = new byte[4];
this.source[0 + pos] = (byte) (data & 0xff);
this.source[1 + pos] = (byte) ((data & 0xff00) >> 8);
this.source[2 + pos] = (byte) ((data & 0xff0000) >> 16);
this.source[3 + pos] = (byte) ((data & 0xff000000) >> 24);
}
/**
* 获取一个FAT项
* @param pos 偏移位置
* @return
*/
private Integer getItem(int pos) {
return (0xff & this.source[0 + pos])
| (0xff00 & (this.source[1 + pos] << 8))
| (0xff0000 & (this.source[2 + pos] << 16))
| (0xff000000 & (this.source[3 + pos] << 24));
}
@Override
public String toString() {
String res = "";
for (int i = 0; i < this.source.length; i++) {
String temp = Integer.toHexString(this.source[i] & 0xFF);
res = res + ((temp.length() == 1)?"0" + temp:"" + temp) + (i==this.source.length - 1?"":((i+1)%16==0?"\n":"\t"));
}
return res;
}
/**
* 添加一个FAT
* @param id ID
* @param location 值
*/
public void save(Integer id,Integer location){
table.put(id,location);
setItem(id,location);
}
/**
* 添加一个FAT
* @param id ID
* @param item 值
*/
public void save(Integer id,FileAllocationTableItem item){
save(id,item.getValue());
}
/**
* 删除一个FAT
* @param id ID
*/
public void clear(Integer id){
save(id,FileAllocationTableItem.EMPTY_CLUSTER_FAT_VALUE);
}
/**
* 标记坏簇
* @param id ID
*/
public void bad(Integer id){
save(id,FileAllocationTableItem.BAD_CLUSTER_FAT_VALUE);
}
}
package cn.edu.zstu.fms.storage;
/**
* 表项数值
* 对应含义
* <p>
* 0x00000000
* 空闲簇,即表示可用
* <p>
* 0x00000001
* 保留簇
* <p>
* 0x00000002 - 0x0FFFFFEF
* 被占用的簇,其值指向下一个簇号
* <p>
* 0x0FFFFFF0 - 0x0FFFFFF6
* 保留值
* <p>
* 0x0FFFFFF7
* 坏簇
* <p>
* 0x0FFFFFF8 - 0x0FFFFFFF
* 文件最后一个簇
*
* @see <a href="https://blog.51cto.com/dengqi/1349327">FAT32文件系统详解</a>
* @see <a href="https://blog.csdn.net/pnzrk/article/details/88943746">FAT32</a>
* @author ShenTuZhiGang
* @version 1.0.0
* @date 2020-12-16 22:42
*/
public enum FileAllocationTableItem {
/*
* 0号FAT为介质类型
* 由于簇号起始于2, 所以FAT表的0号表项与1号表项不予任何簇对应。 FAT32 的0号表项值总是“F8FFFF0F”
* 注意: 可以搜索扇区偏移0字节处的该值(F8FFF0F)以查找FAT表。
* 模拟中由于1扇区/簇,所以簇号起始于6
*/
ZERO_FAT_VALUE(0xF8FFFF0F),
/*
* 1号FAT为文件系统错误标志
* 1号表项可能被用于记录“脏标志”, 以说明文件系统没有被正常卸载或者磁盘表面存在错误。
* 不过此值似乎不重要,正常情况下,1号表项值“FFFFFFFF”或“FFFFFF0F”。
*/
ONE_FAT_VALUE(0xFFFFFF0F),
/*
* 空闲簇,即表示可用
*/
EMPTY_CLUSTER_FAT_VALUE(0x00000000),
/*
* 保留簇
*/
RESERVED_CLUSTER_FAT_VALUE(0x00000001),
/*
* 被占用的簇,其值指向下一个簇号
*/
USED_CLUSTER_FAT_VALUE(0x00000002),
/*
* 保留值
*/
RESERVED_VALUE(0x0FFFFFF0),
/*
* 坏簇
*/
BAD_CLUSTER_FAT_VALUE(0x0FFFFFF7),
/*
* 文件最后一个簇
*/
END_CLUSTER_FAT_VALUE(0x0FFFFFF8),
/*
* 未知值
*/
UNKNOWN_VALUE(0xFFFFFFF0);
FileAllocationTableItem(Integer value) {
this.value = value;
}
private Integer value;
public Integer getValue() {
return value;
}
public static FileAllocationTableItem parse(Integer value) {
if (value == 0xF8FFFF0F) {
return FileAllocationTableItem.ZERO_FAT_VALUE;
} else if (value == 0xFFFFFFFF || value == 0xFFFFFF0F) {
return FileAllocationTableItem.ONE_FAT_VALUE;
} else if (value == 0x00000001) {
return FileAllocationTableItem.RESERVED_CLUSTER_FAT_VALUE;
} else if (value >= 0x00000002 && value <= 0x0FFFFFEF) {
//模拟中由于1扇区/簇,所以簇号实际上起始于6
return FileAllocationTableItem.USED_CLUSTER_FAT_VALUE;
} else if (value >= 0x0FFFFFF0 && value <= 0x0FFFFFF6) {
return FileAllocationTableItem.RESERVED_VALUE;
} else if (value == 0x0FFFFFF7) {
return FileAllocationTableItem.BAD_CLUSTER_FAT_VALUE;
} else if (value >= 0x0FFFFFF8 && value <= 0x0FFFFFFF) {
return FileAllocationTableItem.END_CLUSTER_FAT_VALUE;
} else {
return UNKNOWN_VALUE;
}
}
}
参考文章
更多推荐
已为社区贡献43条内容
所有评论(0)