操作系统原理课程设计:模拟文件管理系统简单介绍和全部源代码

零、前面的话

本系统大部分参考同济大学2016级软件学院学长:洪嘉勇
在此表示感谢!知道了差距和问题,也学习了不少。
幸而因此我的期末课设验收五分钟不到就顺利通过!
分享一下仅供大家学习
。博文三万五千字不容易!记得点赞关注一下哦!

有疑惑和不解欢迎评论一起分析学习

一、项目需求

在内存中开辟一个空间作为文件存储器,在其上实现一个简单的文件系统。
退出这个文件系统时,需要该文件系统的内容保存到磁盘上,
以便下次可以将其恢复到内存中来。

二、具体技术细节

文件存储空间管理可采取显式链接(如FAT)或者其他方法。(即自选一种方法)
空闲空间管理可采用位图或者其他方法。如果采用了位图,可将位图和FAT表合二为一。
文件目录采用多级目录结构。至于是否采用索引节点结构,自选。
目录项目中应包含:文件名、物理地址、长度等信息。

三、开发工具

环境: intellij 语言: Java

四、文件系统管理方案

4.1 存储空间概述

盘区数量:10
盘区大小:1024KB

4.2 存储空间管理方式

FAT:在本次项目中,我的文件系统管理方案采用了显式链接的方式,
在每一个盘区都开了一个文件用来存储当前盘
区所有存储块的使用情况。并记录盘区内所有文件所占用内存块的情况
优点:不存在内外内存碎片,最大程度地利用了盘区空间。

4.3 空闲空间管理方式

位图:在本次项目中,我的文件系统空闲空间管理方案采用了位图。
使用一串0和1来标识内存块的状态。
0为未使用,1表示已经被占用。
创建文件时从最前方开始检索空闲块,确定使用后将0置为1。
优点:一目了然,易于管理。

4.4 文件目录结构

多级目录结构

4.5 FCB

4.5.1 概述

该文件系统的FCB将直接显示在生成的txt文本中,以文本头的形势呈现。
需要编辑内容可以将内容写在FCB下方的划分线内。

4.5.2 内容

大小
文件名
地址
最近更新时间

五、程序操作指南

5.1 特殊文件说明

5.1.1 BitMap&&Fat.txt

该文件存储了盘区的存储块的状态,用0表示还未分配,1表示已经分配
该文件存储了盘区内存在的文件按照链接方式实现的的内存分配情况,列出了对应内存块的位置

5.1.2 recover.txt

该文件是当前盘区的备份文档,在再次启动该应用程序的时候通过读取该文件的信息还原出上次的运行状态,从而实现复盘

5.2 程序概述

5.2.1 界面构成

搜索框 文件树 显示框 底部盘信息栏

5.2.1.1 搜索框

搜索框位于顶部可以在搜索栏中键入文件名或者文件夹名然后点击“start”来进行检索,如果检索成功将直接打开,失败则弹框提醒

5.2.1.2 算法

采用dfs深度搜索的方式

// Search a file
public boolean searchFile(String fileName, File parent){
   
File [] files = parent.listFiles();
for (File myFile:files){
   
if (myFile.getName().equals(fileName)){
   
try {
   
if(Desktop.isDesktopSupported()) {
   
Desktop desktop = Desktop.getDesktop();
desktop.open(myFile);
return true;
}
} catch (IOException e1) {
   
JOptionPane.showMessageDialog(null, myFile.getPath() + " Sorry, some thing
wrong!", "Fail to open",
JOptionPane.ERROR_MESSAGE);
return true;
}
}
if (myFile.isDirectory() && myFile.canRead()){
   
if(searchFile(fileName, myFile)){
   
return true;
}
}
}
return false;
}
5.2.1.3 文件树

文件树位于左侧,呈现文件的目录结构,详情见目录结构

5.2.1.4 显示框

显示框位于程序右侧,用于显示文件的名称、路径、类型、大小和最近修改时间

5.2.1.5 底部盘信息栏

底部盘信息栏位于程序的底部,用于显示当前选中盘区的名称、已使用空间、未使用空间、文件数量

5.2.2 菜单项

create a file(生成一个文件)
create a dir(生成一个文件夹)
delete(删除一个文件或文件夹)
format(格式化)
rename(重命名)

5.3 注意事项

必须先选择一个系统内的文件夹作为模拟工作目录
文件操作需要先选中一个文件树中的节点右键才能进行操作
本程序重在模拟,并不是真正地为文件开了这么大的空间
仅支持生成txt文件,在输入文件名时不需要输入.txt
相同目录下已经存在该文件重命名将失败
文本中将自动生成FCB,不支持用户去修改FCB
非法输入都将导致文件生成失败
如果存档文件recover.txt被破坏,将无法在再次打开该程序时恢复盘区信息

六、文件系统实现功能

6.1 文件目录

文件目录将呈现在
程序的左侧,以十个以数字命名的盘为基目录。
点击文件夹左侧箭头可以将文件夹展开
当执行创建和删除文件等操作,必须重新展开一次父目录才能刷新

6.2 创建文件

6.2.1 概述

选中某一文件后,右键展开功能选项,
选择第一项生成文件或第二项就会弹出对话框要求键入文件名和文件大小。
文件生成成功之后只要重新展开父目录就可以看到新生的文件。
双击程序右侧的显示区的文件就可以打开该文件看到它的FCB

6.2.2 实现方法

通过调用File类的createFile()方法来实现,文件创建成功之后将刷新FAT和位图,如果存储空间不足或是输入非法将导致文件生成失败

// create a file
public boolean createFile(String filePath){
   
boolean result = false;
File file = new File(filePath);
if(!file.exists()){
   
try {
   
result = file.createNewFile();
} catch (IOException e) {
   
e.printStackTrace();
}
}
return result;
}

6.3 删除文件

6.3.1 概述

选中某一文件后,右键展开功能选项,选择第三项删除即可删除所选项

6.3.2 实现方法

通过调用File类的delete()删除 针对文件夹需要递归删除,文件删除成功之后将刷新FAT和位图

// delete a file
public boolean deleteFile(String filePath){
   
boolean result = false;
File file = new File(filePath);
if(file.exists() && file.isFile()){
   
result = file.delete();
}
return result;
}

当执行删除文件操作,必须重新展开一次父目录才能刷新

6.4 重命名(更改当前目录)

6.4.1 概述

选中某一文件后,右键展开功能选项,选择第四项重命名即可对文件或文件夹进行重命名

6.4.2 实现方法

通过调用File类的renameTo()方法进行重命名,如果相同目录下有相同的文件,则重命名将失败
当执行重命名文件操作,必须重新展开一次父目录才能刷新

6.5 打开文件

双击程序中右侧的显示面板中的文件即可打开对应文件

6.6 关闭文件

打开文件之后点击文件上方的关闭按钮就可以将对应文件关闭

6.7 写文件

打开文件之后在FCB的内容下方输入文本即可

6.8 读文件

双击程序右侧的显示面板中的文件即可打开对应文件进行查看

6.9 格式化

6.9.1 概述

选中某一文件夹之后右键选择第四项格式化就可以将该文件夹格式化

6.9.2 实现方法

即递归删除该目录下的所有文件并更新FAT和位图

七、 数据结构

盘区(Block)

八 运行效果图

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

全部源代码

UI.java

package cn.sanlang;

import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.*;
import java.util.ArrayList;

import static java.awt.Toolkit.getDefaultToolkit;

/**
 * Created by sanlang on 2020.11.13
 * function:系统view模块,显示操作界面 初始化系统
 */
public class UI extends JFrame {
   

    private JTree tree;
    private JScrollPane treePane;
    private JScrollPane tablePane;
    private tableModel model = new tableModel();
    private JTable fileTable;
    private JPopupMenu myMenu = new JPopupMenu();
    private JFileChooser chooser;



    private File rootFile;
    private File readMe;
    private FileWriter readMeWrite;

    private Block block1;
    private Block block2;
    private Block block3;
    private Block block4;
    private Block block5;
    private Block block6;
    private Block block7;
    private Block block8;
    private Block block9;
    private Block block10;
    private ArrayList<Block> blocks = new ArrayList<Block>();

    private JLabel blockName = new JLabel("Block Name:");
    private JLabel nameField = new JLabel();
    private JLabel haveUsed = new JLabel("Used:");
    private JLabel usedField = new JLabel();
    private JLabel freeYet = new JLabel("Free:");
    private JLabel freeField = new JLabel();
    private JLabel fileNum = new JLabel("Block's File Number:");
    private JLabel fileNumField = new JLabel();

    private JTextField searchLine = new JTextField();

    private static String helpMessage =
            "<html>" +
                    "<body>" +
                    "<h1>文件系统模拟</h1>" +
                    "<h2>技术细节</h2>" +
                    "<h3>显式链接(FAT)</h3>" +
                    "<ul> <li>用一个专用文件记录分配和未分配的内存块</li> <li>使用链接的方式,不存在内存碎片</li> </ul>" +
                    "<h3>空闲空间管理 —— 位图</h3>" +
                    "<ul> <li>用二进制0和1分别代表未分配的内存块和已经分配的内存块</li> <li>在该项目中位图和FAT进行了合并</li> </ul>" +
                    "<h3>目录结构 —— 多级目录结构</h3>" +
                    "<h3>FCB</h3>" +
                    "<ul> <li>文件类型</li> <li>文件名</li> <li>文件大小</li> <li>文件最近更新时间</li> </ul>" +
                    "<h2>操作说明</h2>" +
                    "<ul> <li>必须先选择一个计算机上的文件夹作为模拟工作目录</li> <li>左侧树状结构即文件目录</li> <li>双击或点击文件夹左侧小图标可以打开文件目录</li> " +
                    "<li>右侧空白处为表格区域,将现实相关文件信息</li> <li>双击表格中的项可以直接打开相关文件</li>" +
                    "<li>下方绿色为盘信息面板,将现实相应盘的相应信息</li>" +
                    "<li>最下方空白处将显示内存块当前状况</li> </ul>" +
                    "<li>在树状结构中选中某一节点,右键即可选择相应的文件操作</li>" +
                    "<li>创建新的文件会要求输入文件名和文件大小(KB)</li>" +
                    "<h2>特别说明</h2>" +
                    "<ul> <li>本程序重在模拟,并不是真正地为文件开了这么大的空间</li> <li>仅支持生成txt,文本文件中直接现实FCB,不支持修改内容</li>" +
                    "<li>对于非法输入都会直接导致文件生成失败</li> <li>如果存档文件recover.txt被破坏,将无法打开文件</li></ul>" +
                    "</body>" +
                    "</html>";

    // Delete a dir
    public static void deleteDirectory(String filePath){
   
        File file = new File(filePath);
        if(!file.exists()){
   
            return;
        }
        if(file.isFile()){
   
            file.delete();
        }else if(file.isDirectory()){
   
            File[] files = file.listFiles();
            for (File myfile : files) {
   
                deleteDirectory(filePath + File.separator + myfile.getName());
            }
            file.delete();
        }
    }

    // Get space
    public double getSpace(File file){
   
        double space = 0;
        try {
   
            BufferedReader reader = new BufferedReader(new FileReader(file));
            reader.readLine();
            space = Double.parseDouble(reader.readLine());
            if (space > 1024){
   
                space = 0.0;
            }
            reader.close();
        } catch (Exception e){
   };
        return space;
    }

    // Update block's information
    public void upDateBlock(Block currentBlock){
   
        fileNumField.setText(String.valueOf(currentBlock.getFileNum()));
        usedField.setText(String.valueOf(currentBlock.getSpace()) + " KB");
        freeField.setText(String.valueOf(1024 - currentBlock.getSpace()) + "KB");
    }

    // Search a file
    public boolean searchFile(String fileName, File parent){
   
        File [] files = parent.listFiles();
        for (File myFile:files){
   
            if (myFile.getName().equals(fileName)){
   
                try {
   
                    if(Desktop.isDesktopSupported()) {
   
                        Desktop desktop = Desktop.getDesktop();
                        desktop.open(myFile);
                        return true;
                    }
                } catch (IOException e1) {
   
                    JOptionPane.showMessageDialog(
                            null,
                            myFile.getPath() + " Sorry, some thing wrong!",
                            "Fail to open",
                            JOptionPane.ERROR_MESSAGE);
                    return true;
                }
            }
            if (myFile.isDirectory() && myFile.canRead()){
   
                if(searchFile(fileName, myFile)){
   
                    return true;
                }
            }
        }
        return false;
    }



    // Ui
    public UI() throws IOException {
   
        this.setTitle("三郎的文件管理模拟系统");
        setLayout(new BorderLayout());
       // Image icon2 = getDefaultToolkit().getImage("icon2.png");
       // this.setIconImage(icon2);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // JFileChooser init
        String path = File.listRoots()[0].getPath();
        String rootPath = new String();
        chooser = new JFileChooser(path);
        chooser.setDialogTitle("选择一个文件夹用来储存和进行模拟");
        //chooser.setBackground(Color.decode("#FDE6E0"));
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        chooser.setPreferredSize(new Dimension(800, 600));
        int result = chooser.showOpenDialog(this);
        if (result == chooser.APPROVE_OPTION){
   
            System.out.println(chooser.getSelectedFile().getAbsolutePath());
            rootPath = chooser.getSelectedFile().getPath();
        }

        // help init
        JLabel help = new JLabel(helpMessage);

        help.setFont(new Font("微软雅黑", Font.CENTER_BASELINE, 20));
        JScrollPane helpPane = new JScrollPane(help);
        helpPane.setPreferredSize(new Dimension(700, 500));
        JOptionPane.showMessageDialog(
                null, helpPane,
                "文件系统模拟说明",
                JOptionPane.DEFAULT_OPTION);

        // Create work space
        rootFile = new File(rootPath + File.separator + "myFileSystem");
        readMe = new File(rootPath + File.separator + "myFileSystem" + File.separator + "ReadMe.txt");

        boolean flag = true;

        // JTree init
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode(new myFiles(rootFile, 0, 10240));
        if (!rootFile.exists()) {
   
            flag = false;
            try {
   
                rootFile.mkdir();
                readMe.createNewFile();
            } catch (Exception e) {
   
                JOptionPane.showMessageDialog(
                        null,
                        "The place is not support to create dir!",
                        "Error", JOptionPane.ERROR_MESSAGE);
                System.exit(0);
            }
            FileWriter writer = new FileWriter(readMe.getPath());
            writer.write("Hello, this my file system!!!\n");
            writer.write("Space: 10 * 1024K = 10M\n");
            writer.write("Free-Space Management:bitmap\n");
            writer.write("Store-Space Management:FAT\n");
            writer.flush();
            writer.close();
        }
        //十个模拟磁盘
        block1 = new Block(1, new File(rootFile.getPath() + File.separator + "1"), flag);
        blocks.add(block1);
        block2 = new Block(2, new File(rootFile.getPath() + File.separator + "2"), flag);
        blocks.add(block2);
        block3 = new Block(3, new File(rootFile.getPath() + File.separator + "3"), flag);
        blocks.add(block3);
        block4 = new Block(4, new File(rootFile.getPath() + File.separator + "4"), flag);
        blocks.add(block4);
        block5 = new Block(5, new 
  • 12
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值