给出一个磁盘块序列:1、2、3、…、500,初始状态所有块为空的,每块的大小为 2k。选择使用
空闲表、空闲盘区链、位示图三种算法之一来管理空闲块。对于基于块的索引分配执行以下步骤:
(1) 随机生成 2k-10k 的文件 50 个,文件名为 1.txt、 2.txt、 …、50.txt,按照上述算法存储到
模拟磁盘中。
(2) 删除奇数.txt(1.txt、3.txt、…、49.txt)文件
(3) 新创建 5 个文件(A.txt、B.txt、C.txt、D.txt、E.txt),大小为:7k、5k、2k、9k、3.5k,按照与(1)
相同的算法存储到模拟磁盘中。
(4) 给出文件 A.txt、B.txt、C.txt、D.txt、E.txt 的盘块存储状态和所有空闲区块的状态。
File 类定义
public class File {
public String fileName;
public double size; //文件大小/KB
public int startBlockId; //起始盘块号
public int blockNum; //盘块数
public File() {}
public File(String fileName, int startBlockId, double size, int blockNum) {
this.fileName = fileName;
this.size = size;
this.startBlockId = startBlockId;
this.blockNum = blockNum;
}
@Override
public String toString() {
return "name =" + fileName + " size =" + size + "KB startBlockId =" + startBlockId + " blockNumber =" + blockNum;
}
}
Region类定义
程序用空闲盘块表算法来管理空闲块, 所以定义空闲区域 Region 类, 表示空闲表中的一项,
public class Region {
public int startBlockId;
public int size;
public Region(int startBlockId, int size) {
this.startBlockId = startBlockId;
this.size = size;
}
@Override
public String toString() {
return "startBlockId=" + startBlockId + " size=" + size;
}
}
根据 fileName 和 size 创建文件,根据 size 求出该文件占用的盘块数 s, 再去遍历空闲表 table, 直
到找出一个空闲表中的表项 size>=s, 如果正好相等, 就表示要恰好占用一个表项, 直接从表中移除,
如果大于要求的空间, 则切分表项, 修改表项的 size 大小. 申请到足够空间后, 创建文件对象 file, 并
加入到 map 集合中. 标示出该文件已存在于文件系统中且唯一.
删除操作, 首先从 map 集合中根据 fileName 移除相应的 file 对象, 再释放占用空间. 此时分三种
情况:
public class FileOperator {
private int size; //磁盘块数 1 to size
private List<Region> table = new ArrayList<>(); //空闲表
private Map<String, File> map = new HashMap<>(); //存储文件状态
public FileOperator(int size) {
this.size = size;
table.add(new Region(1, size)); //初始状态, 空闲表只有一项
}
/**
* 创建文件, 更新空闲表数据
* @param fileName
* @param size 接收double类型数据, 内部转换成盘块size
*/
public void create(String fileName, double size) {
int s = getBlockNum(size);
for (Region r : table) {
if (s == r.size) { //占用一个表项
File file = new File(fileName, r.startBlockId, size, s);
map.put(fileName, file);
table.remove(r);
return;
} else if (size < r.size) { //切分一个表项
File file = new File(fileName, r.startBlockId, size, s);
map.put(fileName, file);
r.startBlockId += s;
r.size -= s;
return;
} else {
continue;
}
}
//磁盘空间不足
System.out.println("file: " + fileName + " size: " + size + ": OutOfDiskError");
}
/**
* 删除文件
* case 1, 与前驱合并
* case 2, 与后继合并
* case 3, 插入到相应位置
* @param fileName
*/
public void delete(String fileName) {
File file = map.remove(fileName);
if (file != null) {
Region r = new Region(file.startBlockId, file.blockNum);
insertToTable(r);
}
}
/**
* 文件大小size到占用盘块数据的映射, 默认盘块大小2K
* @param size
* @return
*/
private int getBlockNum(double size) {
int s = (int)Math.ceil(size);
if (s%2 == 0) {
return s >> 1;
} else {
return (s >> 1) + 1;
}
}
public void insertToTable(Region re) {
// if (re.startBlockId > table.get(table.size() - 1).startBlockId) { //插入末尾
// table.add(re);
// return;
// }
//相邻
for (int i = 0; i < table.size(); i++) { //相邻处理
Region r = table.get(i);
if (r.startBlockId == (re.startBlockId + re.size)) { //re的后继是r的前驱, 与后继合并
r.size += re.size;
r.startBlockId = re.startBlockId;
return;
} else if (r.startBlockId + r.startBlockId == re.startBlockId) { //r 的后继是re 的前驱, 与前驱合并
r.size += re.size;
return;
} else {
continue;
}
}
//插入
table.add(re);
int sStart = re.startBlockId;
int sSize = re.size;
int i = table.size() - 2;
for (; i >= 0; i--) {
if (table.get(i).startBlockId > re.startBlockId) {
Region rr = table.get(i);
table.get(i + 1).startBlockId = rr.startBlockId;
table.get(i + 1).size = rr.size;
} else {
break;
}
}
table.get(i + 1).startBlockId = sStart;
table.get(i + 1).size = sSize;
}
public void printTable() {
System.out.println("空闲区块: ");
for (Region r : table) {
System.out.println(r.toString());
}
}
/**
*
* @param fileName
*/
public void printAttribute(String fileName) {
if (map.containsKey(fileName)) {
System.out.println(map.get(fileName));
}
}
public void printAttribute() {
System.out.println("文件存储状态(乱序): ");
Set<String> files = map.keySet();
for (String file : files) {
System.out.println(map.get(file).toString());
}
}
}
public static void main(String[] args) {
FileOperator fo = new FileOperator(500);
//随机生成50个文件
for (int i = 0; i < 50; i++) {
fo.create(i + ".txt", ((int)(((Math.random()*8) + 2)*100)/100.0));
}
// 删除奇数文件
for (int i = 1; i < 50; i += 2) {
fo.delete(i + ".txt");
}
//新建文件
fo.create("A.txt", 7);
fo.create("B.txt", 5);
fo.create("C.txt", 2);
fo.create("D.txt", 9);
fo.create("E.txt", 3.5);
//查询文件状态
System.out.println("ABCDE文件状态: ");
fo.printAttribute("A.txt");
fo.printAttribute("B.txt");
fo.printAttribute("C.txt");
fo.printAttribute("D.txt");
fo.printAttribute("E.txt");
System.out.println();
fo.printTable();
fo.printAttribute();
}
代码下载: https://download.csdn.net/download/weixin_41889284/11253284