操作系统课程设计 —— 模拟磁盘文件系统实现 (Java)

2022-01-17 00:00:00 磁盘 系统实现 课程设计

这是我前段时间做了一个操作系统课程设计作业,使用java实现了命令行输入对虚拟文件进行管理。

下面是课程设计要求:

点击这里可以查看详细的要求

题目五  模拟磁盘文件系统实现 
一、课程设计目的 
了解磁盘文件系统的结构、功能和实现。并可练习合作完成系统的团队精神和提高
程序设计能力。 
二、小组人数 建议 3~5 人一组共同完成模拟磁盘文件系统的实现。 选择题目“模拟磁盘文件系统实现”的小组在最终提交时须公开演示及讲解。 由于这个题目较复杂,难度和工作量远大于前面几个题目,故小组成员最后得分 也酌情高于选择前面四个题目的同学的分数(高 5~10 分)。 三、编程语言 
建议使用一些 Windows 环境下的程序设计语言如 VC、Java,以借助这些语言的多
线程来模拟并行发生的行为。要求图形界面。 
四、课程设计内容 
设计一个简单的文件系统,用文件模拟磁盘,用数组模拟缓冲区,要求: 
(1) 支持多级目录结构,支持文件的绝对读路径; 
(2) 文件的逻辑结构采用流式结构,物理结构采用链接结构中的显式链接方式; 
(3) 采用文件分配表 FAT; 
(4) 实现的命令包括建立目录、列目录、删除空目录、建立文件、删除文件、显示
文件内容、打开文件、读文件、写文件、关闭文件、改变文件属性。可以采用
命令行界面执行这些命令,也可以采用“右击快捷菜单选择”方式执行命令。 
(5) 后编写主函数对所作工作进行测试。 

下面是我实现的功能:

《操作系统课程设计 —— 模拟磁盘文件系统实现 (Java)》

《操作系统课程设计 —— 模拟磁盘文件系统实现 (Java)》

《操作系统课程设计 —— 模拟磁盘文件系统实现 (Java)》《操作系统课程设计 —— 模拟磁盘文件系统实现 (Java)》《操作系统课程设计 —— 模拟磁盘文件系统实现 (Java)》

以下为源代码

首先是一个FileModel类用来记录文件或目录的相关属性

package com.model;

import java.util.ArrayList;
import java.util.HashMap;

import java.util.Map;

public class FileModel {
	
	public Map<String, FileModel> subMap = new HashMap<String, FileModel>();
	private String name; //文件名或目录名
	private	String type; //文件类型
	private int attr; //用来识别是文件还是目录 
	private int startNum;	//在FAT表中起始位置
	private int size;	//文件的大小
	private FileModel father = null;	//该文件或目录的上级目录
	
	public FileModel(String name, String type, int startNum, int size){
		this.name = name;
		this.type = type;
		this.attr = 2;
		this.startNum = startNum;
		this.size = size;		
	}
	
	public FileModel(String name, int startNum) {
		this.name = name;
		this.attr = 3;
		this.startNum = startNum;
		this.type = "  ";
		this.size = 1;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public int getAttr() {
		return attr;
	}
	public void setAttr(int attr) {
		this.attr = attr;
	}
	public int getStartNum() {
		return startNum;
	}
	public void setStartNum(int startNum) {
		this.startNum = startNum;
	}
	public int getSize() {
		return size;
	}
	public void setSize(int size) {
		this.size = size;
	}

	public FileModel getFather() {
		return father;
	}

	public void setFather(FileModel father) {
		this.father = father;
	}
	
}

接着使用OSManager这个类实现对文件的各种操作

package com.service;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.model.FileModel;
import com.sun.xml.internal.bind.v2.util.FatalAdapter;

public class OSManager {
	
	public Map<String, FileModel> totalFiles = new HashMap<String, FileModel>();
	//定义FAT表
	private int[] fat = new int[128]; 
	//创建根目录 使用fat表的第一项
	private FileModel root = new FileModel("root", 1);
	private FileModel nowCatalog = root;


	
	public OSManager() {
		// TODO Auto-generated consructor stub
		//将FAT表初始化全部为0,并将第一位设为根目录的空间
		for(int i=0; i<fat.length ; i++ ) {
			fat[i] = 0;
		}
		fat[1] = 255; //255表示磁盘块已占用
		fat[0] = 126; //纪录磁盘剩余块数	
		root.setFather(root);
		totalFiles.put("root", root);
	}
	
	public int setFat(int size) {
		int[] startNum = new int[128];
		int i = 2; //纪录fat循环定位
		for(int j=0; j<size; i++) {
			if(fat[i] == 0) {
				startNum[j] = i; //纪录该文件所有磁盘块
				if(j>0) {
					fat[startNum[j-1]] = i; //fat上一磁盘块指向下一磁盘块地址
				}
				j++;
			}
		}
		fat[i-1] = 255;
		return startNum[0]; //返回该文件起始块盘号
	}
	/*
	 * 
	 * 该方法用于删除时释放FAT表的空间
	 */
	public void delFat(int startNum) {
		int nextPoint = fat[startNum];
		int nowPoint = startNum;
		int count = 0;
		while(fat[nowPoint] != 0) {
			nextPoint = fat[nowPoint];
			if(nextPoint == 255) {
				fat[nowPoint] =0;
				count++;
				break;
			} else {
				fat[nowPoint] = 0;
				count++;
				nowPoint = nextPoint;
			}
		}
		fat[0] += count;
	}
	
	/*
	 * 
	 * 以下为追加内容时修改fat表
	 * 
	 */
	
	public void reAddFat(int startNum, int addSize) {
		int nowPoint = startNum;
		int nextPoint = fat[startNum];
		while(fat[nowPoint] != 255) {
			nowPoint = nextPoint;
			nextPoint = fat[nowPoint];
		}//找到该文件终结盘块

		for(int i=2, count = 0; count <addSize ; i++ ) {
			if(fat[i] == 0) {
				fat[nowPoint] = i;
				nowPoint = i;
				count++;
				fat[nowPoint] = 255;//作为当前文件终结盘块
			}
		}
	}
	
	/*
	 * 	以下为创建文件和目录方法
	 * 	14R5黎志亮  
	 */
	public void createFile(String name, String type, int size) {
		
		if(fat[0] >= size) {	//判断磁盘剩余空间是否足够建立文件
			FileModel value = nowCatalog.subMap.get(name); //该目录下是否寻找同名目录或文件
			if(value != null) {  //判断该文件是否存在
				if(value.getAttr() == 3) {   //若存在同名目录 继续创建文件
					int startNum = setFat(size); 
					FileModel file = new FileModel(name, type, startNum, size);
					file.setFather(nowCatalog); //纪录上一层目录
					nowCatalog.subMap.put(name, file); //在父目录添加该文件
					totalFiles.put(file.getName(), file);
					fat[0] -= size;
					System.out.println("创建文件成功!");
					showFile();
				} else if(value.getAttr() == 2) { //若同名文件已存在,创建失败
					System.out.println("创建失败,该文件已存在!"); 
					showFile();
				}
			} else if(value == null) { //若无同名文件或文件夹,继续创建文件
				int startNum = setFat(size); 
				FileModel file = new FileModel(name, type, startNum, size);
				file.setFather(nowCatalog); //纪录上一层目录
				nowCatalog.subMap.put(name, file); //在父目录添加该文件
				totalFiles.put(file.getName(), file);
				fat[0] -= size;
				System.out.println("创建文件成功!");
				showFile();
				}
		} else {
			System.out.println("创建文件失败,磁盘空间不足!");
		}
	
	}
	
	public void createCatolog(String name) {
		
		if(fat[0] >= 1) { //判断磁盘空间是否足够创建文件夹
			
			FileModel value = nowCatalog.subMap.get(name); //判断该目录下是否存在同名目录或文件
			if(value != null) {
				if(value.getAttr() == 2) {
					int startNum = setFat(1);
					FileModel catalog = new FileModel(name, startNum);
					catalog.setFather(nowCatalog); //纪录上一层目录
					nowCatalog.subMap.put(name, catalog);
					fat[0]--;
					totalFiles.put(catalog.getName(), catalog);
					System.out.println("创建目录成功!");
					showFile();
				} else if(value.getAttr() == 3) {
					System.out.println("创建目录失败,该目录已存在!");
					showFile();
				} 
			} else if(value == null) {
				int startNum = setFat(1);
				FileModel catalog = new FileModel(name, startNum);
				catalog.setFather(nowCatalog); //纪录上一层目录
				nowCatalog.subMap.put(name, catalog);
				fat[0]--;
				totalFiles.put(catalog.getName(), catalog);
				System.out.println("创建目录成功!");
				showFile();
			}			
		} else {
			System.out.println("创建目录失败,磁盘空间不足!");
		}
	}
	
	
	/*
	 * 
	 * 以下为显示该目录下的所有文件信息
	 * 
	 */
	 
	public void showFile() {
		System.out.println("***************** < " + nowCatalog.getName() + " > *****************");
       
		if(!nowCatalog.subMap.isEmpty()) {
			for(FileModel value : nowCatalog.subMap.values()) {
				if(value.getAttr() == 3) { //目录文件
					System.out.println("文件名 : " + value.getName());
					System.out.println("操作类型 : " + "文件夹");
					System.out.println("起始盘块 : " + value.getStartNum());
					System.out.println("大小 : " + value.getSize());
					System.out.println("<-------------------------------------->");
				}
				else if(value.getAttr() == 2) {
					System.out.println("文件名 : " + value.getName() + "." + value.getType());
					System.out.println("操作类型 : " + "可读可写文件");
					System.out.println("起始盘块 : " + value.getStartNum());
					System.out.println("大小 : " + value.getSize());
					System.out.println("<-------------------------------------->");
				}
			}
		}
		for(int i =0; i<2; i++)	
		System.out.println();
		System.out.println("磁盘剩余空间 :" + fat[0] + "            " + "退出系统请输入exit");
		System.out.println();
	}
	/*
	 * 
	 * 以下为删除该目录下某个文件
	 * 
	 */
	public void deleteFile(String name) {
		
		FileModel value = nowCatalog.subMap.get(name);
		if(value == null) {
			System.out.println("删除失败,没有该文件或文件夹!");
		} else if(!value.subMap.isEmpty()) {
			System.out.println("删除失败,该文件夹内含有文件!");
		} else {
			nowCatalog.subMap.remove(name);
			delFat(value.getStartNum());
			if(value.getAttr() == 3) {
				System.out.println("文件夹 " + value.getName() + " 已成功删除");
				showFile();
			} else if(value.getAttr() == 2) {
				System.out.println("文件 " + value.getName() + "已成功删除");
				showFile();
			}
		}
	}
	
	/*
	 * 
	 * 以下为文件或文件夹重命名方法
	 * 
	 */
	
	public void reName(String name, String newName) {
		if(nowCatalog.subMap.containsKey(name)) {
			if(nowCatalog.subMap.containsKey(newName)) {
				System.out.println("重命名失败,同名文件已存在!");	
				showFile();
			} else {
				//nowCatalog.subMap.get(name).setName(newName);
				FileModel value = nowCatalog.subMap.get(name);
				value.setName(newName);
				nowCatalog.subMap.remove(name);
				nowCatalog.subMap.put(newName, value);
				System.out.println("重命名成功!");
				System.out.println();
				showFile();
			}
		} else {
			System.out.println("重命名失败,没有该文件!");
			showFile();
		}
	}
	
	/*
	 * 
	 * 以下为修改文件类型
	 * 修改类型需要打开文件后才能操作
	 */
	
	public void changeType(String name, String type) {
		
		nowCatalog = nowCatalog.getFather();
		if(nowCatalog.subMap.containsKey(name)) {
			FileModel value = nowCatalog.subMap.get(name);
			if(value.getAttr() == 2) {
				value.setType(type);
				nowCatalog.subMap.remove(name);
				nowCatalog.subMap.put(name, value);
				System.out.println("修改类型成功!");
				showFile();
			} else if(value.getAttr() == 3) {
				System.out.println("修改错误,文件夹无法修改类型!");
				openFile(value.getName());
			}
		} else {
			System.out.println("修改错误,请检查输入文件名是否正确!");
		}
	}
	
	/*
	 * 以下为打开文件或文件夹方法
	 * 
	 */
	
	public void openFile(String name) {
		if(nowCatalog.subMap.containsKey(name)) {
			FileModel value = nowCatalog.subMap.get(name);
			if(value.getAttr() == 2) {
				nowCatalog = value;
				System.out.println("文件已打开,文件大小为 : " + value.getSize());				
			} else if(value.getAttr() == 3) {
				nowCatalog = value;
				System.out.println("文件夹已打开!");
				showFile();
			}
		} else {
			System.out.println("打开失败,文件不存在!");
		}
	}
	
	/*
	 * 
	 * 以下为向文件追加内容方法
	 * 追加内容需要打开文件后才能操作
	 */
	
	public void reAdd(String name, int addSize) {
		
		if(fat[0] >= addSize) {
			nowCatalog = nowCatalog.getFather();
			if(nowCatalog.subMap.containsKey(name)) {
				FileModel value = nowCatalog.subMap.get(name);
				if(value.getAttr() == 2) {
					value.setSize(value.getSize() + addSize);
					reAddFat(value.getStartNum(), addSize);
					System.out.println("追加内容成功!正在重新打开文件...");
					openFile(name);
				} else{
					System.out.println("追加内容失败,请确认文件名是否正确输入。");					
				}
			} else {
				System.out.println("追加内容失败,请确认文件名是否正确输入!");
				showFile();
			}
		} else {
			System.out.println("追加内容失败,内存空间不足!");
		}
	}
	
	
	/*
	 * 
	 * 以下为返回上一层目录
	 * 
	 */
	
	public void backFile() {
		if(nowCatalog.getFather() == null) {
			System.out.println("该文件没有上级目录!");
		} else {
			nowCatalog = nowCatalog.getFather();
			showFile();
		}
	}
	
	/*
	 * 以下根据绝对路径寻找文件
	 * 
	 */
	
	public void searchFile(String[] roadName) {
		
		FileModel theCatalog = nowCatalog; //设置断点纪录当前目录
		
		if(totalFiles.containsKey(roadName[roadName.length-1])) { //检查所有文件中有无该文件

			nowCatalog = root; //返回根目录
			if(nowCatalog.getName().equals(roadName[0])) {	//判断输入路径的首目录是否root
				System.out.println("yes");
				/*for(String temp:roadName)
					System.out.println(temp);*/
				
				for(int i=1; i<roadName.length; i++) {
					if(nowCatalog.subMap.containsKey(roadName[i])) {
						/*System.out.println(nowCatalog.getName());
						for(Entry<String, FileModel> s : nowCatalog.subMap.entrySet())
							System.out.println("键值对:" + s.getValue().getName());
							*/
						nowCatalog = nowCatalog.subMap.get(roadName[i]); //一级一级往下查

					} else {
						System.out.println("找不到该路径下的文件或目录,请检查路径是否正确");
						nowCatalog = theCatalog;
						showFile();
						break;
					}
				}
				if(roadName.length>1){
					nowCatalog = nowCatalog.getFather(); //返回文件上一级目录 
					showFile();
				}
			} else {
				nowCatalog = theCatalog;
				System.out.println("请输入正确的绝对路径!");
				showFile();
			}
		} else {
			System.out.println("该文件或目录不存在,请输入正确的绝对路径!");
			showFile();
		}
	}
	
	/*
	 * 以下为打印FAT表内容
	 * 
	 */
	public void showFAT() {

		for(int j=0; j<125; j+=5) {
			System.out.println("第几项 | " + j + "        " + (j+1) + "        " + (j+2) + "        "
					+ (j+3) + "        " + (j+4));
			System.out.println("内容    | " + fat[j] + "        " + fat[j+1] + "        " + fat[j+2]
					 + "        " + fat[j+3] + "        " + fat[j+4]);
			System.out.println();
		}
		int j = 125;
		System.out.println("第几项 | " + j + "        " + (j+1) + "        " + (j+2));
		System.out.println("内容    | " + fat[j] + "        " + fat[j+1] + "        " + fat[j+2]);
		System.out.println();
		showFile();
	}
}

最后使用TestFileSystem这个类实现菜单功能

package com.testsystem;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.service.OSManager;

public class TestFileSystem {
	public static void main(String[] args) {
		try{
		OSManager manager = new OSManager();
		meun(manager);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void meun(OSManager manager) {
		Scanner s = new Scanner(System.in);
		String str = null;
		System.out.println("***********" + "欢迎使用文件模拟操作系统" + "***********");
		System.out.println();
		manager.showFile();

		System.out.println("请输入命令(输入help查看命令表):");
		while ((str = s.nextLine()) != null) {
			if (str.equals("exit")) {
				System.out.println("感谢您的使用!");
				break;
			}

			String[] strs = editStr(str);
			switch (strs[0]) {
			case "createFile":
				if (strs.length < 4) {
					System.out.println("您所输入的命令有误,请检查");
				} else {
					manager.createFile(strs[1], strs[2],
							Integer.parseInt(strs[3]));
				}
				break;
			case "createCatalog":
				if (strs.length < 2) {
					System.out.println("您所输入的命令有误,请检查!");
				} else {
					manager.createCatolog(strs[1]);
				}
				break;
			case "open":
				if (strs.length < 2) {
					System.out.println("您所输入的命令有误,请检查!");
				} else {
					manager.openFile(strs[1]);
				}
				break;
			case "cd":
				if (strs.length < 2) {
					System.out.println("您所输入的命令有误,请检查!");
				} else {
					manager.openFile(strs[1]);
				}
				break;
			case "cd..":
				manager.backFile();
				break;
			case "delete":
				if (strs.length < 2) {
					System.out.println("您所输入的命令有误,请检查!");
				} else {
					manager.deleteFile(strs[1]);
				}
				break;
			case "rename":
				if (strs.length < 3) {
					System.out.println("您所输入的命令有误,请检查!");
				} else {
					manager.reName(strs[1], strs[2]);
				}
				break;
			case "search": {
				if (strs.length < 2) {
					System.out.println("您所输入的命令有误,请检查!");
				} else {
					String[] roadName = strs[1].split("/");
					/*for(String temp : strs)
						System.out.println(temp);
					System.out.println(Arrays.toString(strs));
					System.out.println(Arrays.toString(roadName));*/
					manager.searchFile(roadName);
				}
				break;
			}
			case "showFAT":
				manager.showFAT();
				break;
			case "addContents":
				if (strs.length < 3) {
					System.out.println("您所输入的命令有误,请检查!");
				} else {
					manager.reAdd(strs[1], Integer.parseInt(strs[2]));
				}
				break;
			case "changeType":
				if (strs.length < 3) {
					System.out.println("您所输入的命令有误,请检查!");
				} else {
					manager.changeType(strs[1], strs[2]);
				}
				break;
			case "help": {
				System.out.println("命令如下(空格不能省略):");
				System.out
						.println("createFile FileName fileType fileSize");
				System.out.println("<创建文件 如:createFile marco txt 5 >");
				System.out.println();
				System.out
						.println("createCatalog FatalogName");
				System.out.println("<创建目录 如:createCatalog myFile >");
				System.out.println();
				System.out
						.println("open Name.FileTypt");
				System.out.println("<打开文件 如:open marco.txt >");
				System.out.println();
				System.out.println("cd CatalogName");
				System.out.println("<打开目录 如: cd myFile >");
				System.out.println();
				System.out.println("cd..");
				System.out.println("<返回上级目录 如: cd..");
				System.out.println();
				System.out
						.println("delete FileName/CatalogName");
				System.out.println("<删除文件或目录(目录必须为空)如:delete marco >");
				System.out.println();
				System.out
						.println("rename FileName/CatalogName NewName");
				System.out.println("<重命名文件或目录 如: rename myfile mycomputer >");
				System.out.println();
				System.out
						.println("search FileAbsolutedRoad/CatalogAbsolutedRoad");
				System.out.println("<根据绝对路径寻找文件或者目录 如: search root/marco >");
				System.out.println();
				System.out.println("showFAT");
				System.out.println("<查看FAT表 如: showFAT>");
				System.out.println();
				System.out.println();
				System.out.println("下列命令需要打开文件后操作:");
				System.out
						.println("addContents FileName ContentSize");
				System.out.println("<在文件内增加内容 如:ddContents marco 4 >");
				System.out.println();
				System.out
						.println("changeType FileName newType");
				System.out.println("<改变文件类型 如: changeType marco doc>");
				System.out.println();
				break;
			}
			default:
				for(String st : strs)
					System.out.println(st);
				System.out.println("您所输入的命令有误,请检查!");
			}
			System.out.println("请输入命令(输入help查看命令表):");
		}
	}

	public static String[] editStr(String str) {
		Pattern pattern = Pattern.compile("([a-zA-Z0-9.\\\\/]*) *");// 根据空格分割输入命令
		Matcher m = pattern.matcher(str);
		ArrayList<String>  list = new ArrayList<String>();
		while(m.find()){
			list.add(m.group(1));
		}
		String[] strs = list.toArray(new String[list.size()]);
		
		for (int i = 1; i < strs.length; i++) { // 判断除命令以外每一个参数中是否含有 "."
			int j = strs[i].indexOf(".");
			if (j != -1) { // 若含有"." 将其切割 取前部分作为文件名
				String[] index = strs[i].split("\\."); // 使用转义字符"\\."
				strs[i] = index[0];
			}
		} 
		return strs;
	}
}

    原文作者:Laichilueng
    原文地址: https://blog.csdn.net/Laichilueng/article/details/54669370
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

相关文章