基于Java开发的(控制台)模拟的多用户多级目录的文件系统

news2024/11/17 2:36:44

多级文件系统

1 设计目的

为了加深对文件系统内部功能和实现过程的理解,设计一个模拟的多用户多级目录的文件系统,并实现具体的文件物理结构、目录结构以及较为完善的文件操作命令集。

2 设计内容

2.1系统操作

操作命令风格:本文件系统的操作命令风格将采用windows系统的文件操作命令风格,操作命令区分大小写,并能在用户错误地执行某些操作之后给出及时反馈,提供良好的交互体验。

具体的操作:本文件系统将实现以下功能操作:

2.2文件物理结构

本文件系统的文件物理结构将采用顺序结构,即将文件记录存储在一块连续的磁盘空间中。相应地,磁盘空间的分配也采用连续分配的方式。

2.3文件目录结构

本文件系统的文件目录结构将采用树形目录结构。树形目录结构的优点是可以更方便有效地管理用户的文件,特别是在多用户系统且用户的文件数量较多的情境中。树形目录结构也是目前最为流行的文件目录结构之一,比较符合大多数人的使用习惯。

2.4磁盘空间管理

本文件系统的磁盘空间管理采用位示图来进行管理,用户可以使用show命令来显示磁盘空间位示图以查看当前系统的磁盘空间使用情况。

2.5额外功能

本文件系统提供查看系统操作命令集的功能,用户可以使用help命令来查看本系统已实现的功能,优化用户的使用体验。

另外,本文件系统还提供了将创建的文件保存到电脑本地的功能,以便用户下次使用本系统时能查看自己所创建的文件。2.6编程语言和环境

本文件系统的编程语言采用Java语言,运行环境为JDK 1.8版本及以上。

3 设计步骤

3.1需求分析

3.1.1功能需求

本文件系统的功能模块将细分为三个模块:用户管理模块、文件管理模块、系统管理模块。各个模块的功能需求如表3.1~表3.3所示。

**表 3. SEQ 表 _ ARABIC \s 1 1 用户管理模块功能需求_

名称详细描述
用户注册用户使用register命令注册一个系统用户,并要求输入用户名和密码
用户登录用户使用login命令进行登录,需要输入用户名和密码进行身份校验
用户注销用户使用logout命令注销当前已登录的用户

表 3.2 文件管理模块功能需求

名称详细描述
创建目录用户使用mkdir命令创建一个文件目录,文件目录名不能和当前目录下的文件或文件目录重名,并且不区分大小写
列出文件用户使用dir命令列出当前目录下的所有文件的详细信息,支持使用路径名
切换目录用户使用cd命令切换到目标目录,路径名使用windows系统的风格
创建文件用户使用create命令创建一个文件,文件名不能和当前目录下的文件或文件目录重名,并且不区分大小写
打开文件用户使用open命令打开一个文件,支持使用路径名
读取文件用户使用read命令读取一个已打开的文件,可向后读取和向前读取
写入文件用户使用write命令向一个已打开的文件写入记录
关闭文件用户使用close命令关闭一个已打开的文件
删除文件用户使用delete命令删除一个存在的文件或文件目录,支持使用路径名
重命名文件用户使用rename命令对一个文件或文件目录进行重命名,新的名称不能和当前目录下的文件或文件目录重名,并且不区分大小写

表 3.3 系统管理模块功能需求

名称详细描述
显示帮助用户使用help命令查看当前系统支持的操作命令以及使用方法
显示磁盘位示图用户使用show命令查看当前磁盘空间的位示图和其他信息
退出系统用户使用exit命令退出文件系统,系统在退出前会保存用户信息、文件信息和磁盘空间信息
3.1.2性能需求

本文件系统具有较高的响应比,在文件信息不是特别多的时候能够做到0延迟响应。并且本文件系统运行所需的内存空间比较小,保存文件的大小与文件信息的多少成正比。

3.1.3交互需求

用户与本文件系统的交互在控制台中进行,并且可以方便地查看系统操作命令,降低了用户的学习使用成本。

本文件系统具有良好的信息展示功能,包括文件信息展示、文件内容展示、操作命令展示、位示图展示,使用户可以及时地获取自己所需要的信息。

本文件系统具有友好的错误信息反馈。在用户想要执行一项不被允许的操作时(如打开不存在的文件)能够给予用户正确、简洁的引导式的错误反馈。

3.2概要设计

3.2.1设计思想

本文件系统在设计上采用模块化的思想,将服务类型一致的功能划分到同一个模块,使项目整体上比较清晰。并且每个模块都提供对外调用的接口,这样就能让其他模块在需要的时候调用本模块的某些功能,实现复用。

3.2.2模块设计

本文件系统分为用户管理模块、文件管理模块和系统管理模块三个大模块。其中各个模块细分如下:

  • 用户管理模块:负责提供用户注册、用户登录、用户注销三个功能。
  • 文件管理模块:文件管理模块还可分为文件模块、文件目录模块以及磁盘模块三个小模块。其中:
    • 文件模块:负责提供创建文件、打开文件、读取文件、写入文件、关闭文件、删除文件以及重命名文件共七个功能。
    • 文件目录模块:负责提供创建目录、切换目录、列出文件以及解析路径共四个功能。
    • 磁盘模块:负责提供存储记录、释放磁盘空间、读取记录、保存磁盘数据以及加载磁盘数据共五个功能。
    • 系统管理模块:系统管理模块有一个下属模块:打印信息模块,该模块负责提供显示文件列表、显示文件内容、显示帮助列表以及显示位示图共四个功能。

具体的系统模块图如图3.1所示。

图3.1 系统模块图

3.2.3抽象数据类型定义

系统用户信息实体类定义如下:

public class User implements Serializable {

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;
}

文件控制块实体类定义如下:

public class FileControlBlock implements Serializable {

    /**
     * 是否是目录文件
     */
    private boolean isDirectory;

    /**
     * 文件名(包括了拓展名)
     */
    private String fileName;

    /**
     * 拓展名
     */
    private String suffix;

    /**
     * 起始盘块号
     */
    private Integer startBlock;

    /**
     * 所占用的盘块数
     * 文件大小 = 一个盘块的大小 * 所占用的盘块数
     */
    private Integer blockNum;

    /**
     * 文件属性:保护码列表
     */
    private List<ProtectType> protectTypeList;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 最后一次修改时间
     */
    private LocalDateTime updateTime;
}

树形目录结构实体类定义如下:

public class Directory implements Serializable {

    /**
     * 文件控制块
     */
    private FileControlBlock fileControlBlock;

    /**
     * 在树形目录结构中的位置
     */
    private Integer index;

    /**
     * 文件夹属性:子目录项集合
     */
    private List<Directory> childDirectory;

    /**
     * 父目录项的位置
     */
    private Integer parentIndex;

打开的文件信息实体类定义如下:

public class ActiveFile {

    /**
     * 文件控制块
     */
    private FileControlBlock fileControlBlock;

    /**
     * 文件记录
     */
    private List<Character> fileRecord;

    /**
     * 读指针
     */
    private Integer readPtr;

    /**
     * 写指针
     */
    private Integer writePtr;
}

虚拟磁盘空间实体类定义如下:

public class Disk implements Serializable {

    /**
     * List<Character>: 表示一个盘块
     * List<List<Character>>: 表示所有盘块的集合,即一个磁盘
     */
    private List<List<Character>> disk;
    /**
     * 表示存储在该磁盘上的系统用户集
     */
    private Map<String, User> userMap;
    /**
     * 表示存储在该磁盘上的所有文件控制块
     */
    private List<FileControlBlock> fileControlBlockList;
    /**
     * 表示存储在该磁盘上的树形结构目录,第0个元素为根目录
     */
    private List<Directory> directoryStruct;
    /**
     * 表示存储在该磁盘上的磁盘位示图
     */
    private Integer[][] bitmap;
}
3.2.4主程序的流程图

主程序的流程图如图3.2所示。

图3.2 主程序流程图

3.3详细设计

3.3.1系统算法IPO表

表3.4~表3.26展示了本文件系统的各个功能的具体实现算法IPO表,介绍了各功能模块的编号、模块、日期、作者、被调用模块、输入输出、数据处理与相关数据。如下所示:

表3.4用户注册IPO表

表3.5用户登录IPO表

表3.6用户注销IPO表

表3.7创建文件IPO表

表3.8打开文件IPO表

表3.9读取文件IPO表

表3.10写入文件IPO表

表3.11关闭文件IPO表

表3.12删除文件IPO表

表3.13重命名文件IPO表

表3.14创建目录IPO表

表3.15切换目录IPO表

表3.16列出文件IPO表

表3.17解析路径IPO表

表3.18存储记录IPO表

表3.19释放磁盘空间IPO表

表3.20读取记录IPO表

表3.21保存磁盘数据IPO表

表3.22加载磁盘数据IPO表

表3.23显示文件列表IPO表

表3.24显示文件内容IPO表

表3.25显示帮助列表IPO表

表3.26显示位示图IPO表

3.4调试分析

一开始在实现树形结构目录的时候,我的文件目录项实体类是这样的:

public class Directory implements Serializable {

    /**
     * 文件控制块
     */
    private FileControlBlock fileControlBlock;

    /**
     * 文件夹属性:子目录项集合
     */
    private List<Directory> childDirectory;

    /**
     * 父目录项
     */
    private Directory parentDirectory;
}

在一个目录项之中,持有其父目录项的引用,如果该目录项是目录文件的话,还持有归属于它的子目录项的集合,这样便可以实现一个树形结构的目录。而在磁盘中只要持有一个对根目录的引用就可以查找到所有的目录项,这样是很方便的一种实现方案。

但是,这样的实体类在程序实际运行起来的时候是有问题的。假设有这样的情形:directoryA是一个表示目录文件的目录项,directoryB是一个表示数据文件的目录项,并且directoryB的父目录项是directoryA。这样的关系,在程序中表现为,directoryA的childDirectory属性中持有对directoryB的引用,而directoryB的parentDirectory属性持有对directoryA的引用,这样就造成了循环引用。

这样的循环引用问题,在Java的序列化和反序列化的时候表现的尤为明显。因为本文件系统可以将系统运行过程中的磁盘数据保存到本地文件中,也可以将本地文件中的磁盘数据加载到程序中,前者是通过序列化实现的,后者是通过反序列化实现的。但是由于循环引用的问题,在进行序列化和反序列化的时候,会报栈溢出的错误,导致磁盘数据加载不了(表现为找不到本该存在的目录项)。

当时发现这个问题的时候,我通过IDEA的debug功能一步一步地调试,最终定位到问题的根源以及想出了解决方案。改进后的文件目录项实体类如下所示:

public class Directory implements Serializable {

    /**
     * 文件控制块
     */
    private FileControlBlock fileControlBlock;

    /**
     * 在树形目录结构中的位置
     */
    private Integer index;

    /**
     * 文件夹属性:子目录项集合
     */
    private List<Directory> childDirectory;

    /**
     * 父目录项的位置
     */
    private Integer parentIndex;
}

这样进行了修改之后,在磁盘中要保存的是整个树形目录结构的所有目录项的列表,如下所示:

public class Disk implements Serializable {

    ...

    /**
     * 表示存储在该磁盘上的树形结构目录,第0个元素为根目录
     */
    private List<Directory> directoryStruct;

    ...
}

3.5系统测试

3.5.1 help命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
help显示本系统的帮助列表help命令功能正常

实际测试结果如下图所示:

3.5.2 exit命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
exit退出本系统exit命令功能正常

实际测试结果如下图所示:

3.5.3 register命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
register注册用户失败:用户名不能为空缺少[用户名]参数
register pw注册用户失败:密码不能为空缺少[密码]参数
[pw]这个用户没有被注册register pw 123注册用户成功register命令功能正常
[pw]这个用户已被注册register pw 123注册用户失败:该用户已存在[pw]是一个已存在的用户,不能重复注册

实际测试结果如下图所示:

3.5.4 login命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
login用户登录失败:该用户不存在缺少[用户名]参数,系统会判定[用户名]为空字符
login pw用户登录失败:密码错误缺少 [密码]参数,系统会判定[密码]为空字符
[pw]这个用户已被注册,且密码不是456login pw 456用户登录失败:密码错误[pw]这个用户的密码不正确
[unknown]这个用户没有被注册login unknown 123用户登录失败:该用户不存在[unknown]这个用户不存在(没有注册过)
[pw]这个用户已被注册,且密码是123login pw 123登录成功用户名和密码都正确,登录成功

实际测试结果如下图所示:

3.5.5 logout命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
已登录了某个用户logout注销成功logout命令功能正常
当前没有登录用户logout用户注销失败:当前没有登录用户logout命令功能正常

实际测试结果如下图所示:

3.5.6 show命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
show显示位示图信息show命令功能正常

实际测试结果如下图所示:

注意:以下命令能够正确执行前提都是要在已进行了登录的情况下,如果没有进行登录,系统会给出错误提示信息。所以下述命令的测试都是在已登录了的情况下进行的测试,此前提条件不再赘述,忘悉知。

3.5.7 mkdir命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
mkdir创建目录失败:文件名不能为空缺少[目录名]这个参数,系统会判定目录名为空字符
当前目录下不存在[os]这个子目录mkdir os创建成功,使用[dir]命令可以查看到[os]这个目录的信息mkdir命令功能正常
当前目录下存在[os]这个子目录mkdir os创建目录失败:文件名重复同一个目录中的文件不能重名

实际测试结果如下图所示:

3.5.8 dir命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
dir列出当前目录下面所有文件的信息dir命令功能正常

实际测试结果如下图所示:

3.5.9 cd命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
cd仍在当前目录如果缺少[目录路径]参数,则停留在当前目录下
当前目录下存在[os]这个子目录cd os进入到os目录cd命令功能正常
当前目录下不存在[os]这个子目录cd os切换目录失败:找不到对应目录cd命令功能正常
存在上一级目录cd …返回到上一级目录cd命令功能正常

实际测试结果如下图所示:

3.5.10 create命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
create创建文件失败:文件名不能为空缺少[文件名]这个参数,系统会判定文件名为空字符
当前目录下不存在[a.txt]这个文件create a.txt创建文件成功,使用[dir]命令可以查看到[a.txt]的信息create命令功能正常
当前目录下存在[a.txt]这个文件create a.txt创建文件失败:文件名重复同一个目录中的文件不能重名
当前目录下存在[a.txt]这个文件create A.txt创建文件失败:文件名重复本系统的文件名不区分大小写

实际测试结果如下图所示:

3.5.11 open命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
open打开文件失败:文件名不能为空缺少[文件名]这个参数,系统会判定文件名为空字符
当前目录下不存在[b.jpg]这个文件open b.jpg打开文件失败:文件不存在open命令功能正常
当前目录下存在[a.txt]这个文件open a.txt打开文件成功,显示出文件中的内容open命令功能正常

实际测试结果如下图所示:

3.5.12 close命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
当前存在已打开的文件close关闭成功close命令功能正常
当前不存在已打开的文件close关闭文件失败:当前没有文件被打开close命令功能正常

实际测试结果如下图所示:

3.5.13 write命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
当前不存在已打开的文件write,然后输入文件内容,以“###”结尾写入文件失败:请先打开文件再进行写入write命令功能正常
当前存在已打开的文件write,然后输入文件内容,以“###”结尾写入成功,控制台会回显文件的所有内容(包括刚刚写入的内容)write命令功能正常

实际测试结果如下图所示:

3.5.14 read命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
当前存在已打开的文件read显示空字符缺少[要读取的记录个数]参数,系统会判定要读取的记录个数为0
当前存在已打开的文件,且(当前读指针 + 5)< 文件长度read 5显示读取出来的5个字符read命令功能正常
当前存在已打开的文件,且(当前读指针 - 4)>= 0read -4显示读取出来的4个字符read命令支持向后读取

实际测试结果如下图所示:

3.5.15 delete命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
delete删除文件失败:文件名不能为空缺少[文件名]参数,系统会判定文件名为空字符
当前目录下不存在[b.jpg]这个文件delete b.jpg删除文件失败:找不到对应文件delete命令功能正常
当前目录下存在[a.txt]这个文件delete a.txt删除成功,使用[dir]命令查看a.txt文件不存在delete命令功能正常

实际测试结果如下图所示:

3.5.16 rename命令测试

测试数据如下表:

前提条件命令输入执行结果结果分析
rename重命名文件失败:文件名不能为空缺少[文件名]参数,系统会判定文件名为空字符
rename b.jpg重命名文件失败:文件名不能为空缺少[新文件名]参数,系统会判定新文件名为空字符
当前目录下不存在[b.jpg]这个文件rename b.jpg c.mp3重命名文件失败:文件不存在rename命令功能正常
当前目录下存在[a.txt]这个文件rename a.txt c.mp3重命名成功,使用[dir]命令可查看a.txt已变为c.mp3rename功能正常

实际测试结果如下图所示:

3.6使用说明

3.6.1操作命令说明

本文件系统支持的所有操作命令已在“帮助列表”中列出。想要查看“帮助列表”时只要键入 help 命令即可,如下所示:

现在对本文件系统中的几种操作命令格式做说明:

①无参数命令:例如help、show、exit、dir等都是无参数命令。在使用无参数命令时,只需要键入对应的命令即可,不需要输入额外的参数。如果输入的额外的参数,系统会默认把它丢弃掉,也并不影响使用。

②单参数命令:例如mkdir、create、open等都是单参数命令。使用单参数命令时,输入对应的命令之后,要输入一个(或者至少一个)空格,然后输入正确的参数,最后回车即可。在上述“帮助列表”中的“用法”中,方括号框中表示的是要输入的参数。例如mkdir [目录名],该命令正确的用法是“mkdir test”,表示创建一个名为“test”的新目录。

③多参数命令:例如register、login等都是要输入一个以上参数的命令。在使用多参数命令时,参数和参数之间要使用一个空格进行分隔开。另外,参数的个数要对应。例如在使用login [用户名] [密码],如果输入“login 123”,系统会把“123”当成用户名来识别,而该命令缺少了密码这个参数,系统给出错误提示。

另外,对本文件系统采用的文件路径格式做如下说明:

①目录名与目录名(或文件名)之前用路径分隔符“/”分隔开。例如“cd test/word”表示进入到当前目录下的test文件夹下的word文件夹中。

②全部采用相对路径

③“…”表示上一级目录。例如“cd …”表示回退到上一级目录。

3.6.2磁盘数据保存说明

本文件系统在启动的时候会加载“固定路径”下的“磁盘文件”中的磁盘数据,在正常退出的时候会保存磁盘数据到“固定路径”下的“磁盘文件”中。

“固定路径”是指程序运行文件所在目录中的save文件夹。“磁盘文件”是指save文件夹中的一个名为disk.ser的文件,本文件系统的所有磁盘数据都会保存进里面。如果本文件系统启动的时候找不到disk.ser文件(或save文件夹),系统会初始化磁盘,相当于一个新激活的系统。

本文件系统在正常退出(使用exit命令退出)的之前,会保存当前的磁盘数据到save文件夹中的disk.ser文件中。如果disk.ser文件不存在,会新建一个disk.ser文件;如果disk.ser文件存在,则会进行覆盖写入操作。

3 经验与体会

我的经验和体会是:

①在编程实现多级文件系统之前,要先确定好文件的逻辑结构、文件的物理结构、文件控制块信息、树形目录结构的表现形式、磁盘空间的表示显示、文件记录在磁盘中的表现形式、磁盘空间的分配方式、磁盘空间的管理形式等重要问题。只有思考了以上问题以及确定好具体的实现方案之后,才能着手与正式的编程实现,否则就在编程的同时遇到很多具有极强关联性的问题,导致了编程后期可能要对系统进行重构。

②在设计本文件系统的交互的时候,要考虑到用户的使用感受,应该使用户能以尽量简单的形式使用本系统,操作命令的输入不要过于冗余而繁杂。在这个方面可以参考很多优秀的操作系统的实现方式,比如Linux和Windows系统。

4 重要数据结构或疑难部分说明

4.1重要数据结构

大部分重要数据结构已经在之前的设计步骤中的需求分析的抽象数据类型定义小节中进行了说明,这里便不再赘述。关于树形结构目录的实现则在实体类Directory中。

4.2疑难部分说明

除了树形目录结构的具体实现比较难之外(该实现已在调试分析中进行说明),另一个疑难部分就是在存储文件记录时为文件记录分配磁盘空间和修改位示图的具体实现。存储文件记录的具体实现为:

public CommonResult<FileControlBlock> storeRecord(FileControlBlock fileControlBlock, List<Character> record) {
    if (CollectionUtil.isEmpty(record)) {
        return CommonResult.operateSuccess(null);
    }

    // 修改位示图,为重新分配盘块做准备
    changeBitmapStatus(fileControlBlock.getStartBlock(), fileControlBlock.getBlockNum(), true);
    // 计算存储该长度记录所需要的盘块数量
    Integer requiredNum = Math.ceilDivide(record.size(), DiskConstant.BLOCK_SIZE);

    int count = 0;
    int startBlockId = DiskConstant.RECORD_START_BLOCK;

    for (int i = 0; i < DiskConstant.BITMAP_ROW_LENGTH; i++) {
        for (int j = 0; j < DiskConstant.BITMAP_LINE_LENGTH; j++) {
            // 如果该盘块空闲
            if (DiskConstant.BITMAP_FREE.compareTo(Memory.getInstance().getBitmap()[i][j]) == 0) {
                if (count == 0) {
                    // 记下起始盘块号: 当前行 * 总列数 + 当前列
                    startBlockId = i * DiskConstant.BITMAP_LINE_LENGTH + j;
                }

                count++;
                if (count == requiredNum) {
                    // 如果有足够的连续盘区供存储,则进行存储,并改变位示图的相应状态
                    storeToDisk(startBlockId, record);
                    changeBitmapStatus(startBlockId, requiredNum, false);
                    return CommonResult.operateSuccess(fileControlBlock.setStartBlock(startBlockId).setBlockNum(requiredNum));
                }
            } else {
                // 因为是连续分配,如果该盘块不空闲则要重新计数
                count = 0;
            }
        }
    }

    return CommonResult.operateFailWithMessage("[分配盘块失败]: 磁盘空间不足");
}

在该方法中调用了两个关键的方法:storeToDisk(startBlockId, record)和changeBitmapStatus(startBlockId, requiredNum, false)。

其中的storeToDisk(startBlockId, record)方法的作用是将文件记录存储在磁盘中。传入参数startBlockId表示起始盘块号,传入参数record表示待存储的文件记录。其具体实现为:

private void storeToDisk(Integer startBlockId, List<Character> record) {
    int index = 0;
    int blockId = startBlockId;
    Disk disk = DataCache.getInstance().getDisk();

    // 可以直接覆盖掉原来的磁盘中的记录
    for (Character ch : record) {
        if (index >= DiskConstant.BLOCK_SIZE) {
            // 如果一个盘块的空间被用完了,则使用下一个盘块来进行存储
            blockId++;
            index = 0;
        }

        disk.getDisk().get(blockId).add(index, ch);
        index++;
    }

    while (index < DiskConstant.BLOCK_SIZE && disk.getDisk().get(blockId).size() > index) {
        // 擦除最后一个盘块中没有用到的空间
        disk.getDisk().get(blockId).set(index, null);
        index++;
    }
}

其中的changeBitmapStatus(startBlockId, requiredNum, false)方法的作用是更改相应的位示图的状态(仅适用于连续分配的方式)。传入参数startBlockId表示起始盘块号,传入参数blockNum表示要更改的盘块数量,传入参数changeToFree表示要更改的状态(true-表示空闲状态,false-表示已分配状态)。其具体实现为:

private void changeBitmapStatus(Integer startBlockId, Integer blockNum, boolean changeToFree) {
    if (Objects.isNull(startBlockId) || startBlockId < DiskConstant.RECORD_START_BLOCK ||
        startBlockId >= DiskConstant.BLOCK_NUM || blockNum <= 0) {
        return;
    }

    // 解析该盘块在位示图中的第几行
    int row = startBlockId / DiskConstant.BITMAP_LINE_LENGTH;
    // 解析该盘块在位示图中的第几列
    int line = startBlockId % DiskConstant.BITMAP_LINE_LENGTH;
    for (int i = 0; i < blockNum; i++) {
        Memory.getInstance().getBitmap()[row][line] = changeToFree ? DiskConstant.BITMAP_FREE : DiskConstant.BITMAP_BUSY;
        if (line >= DiskConstant.BITMAP_LINE_LENGTH - 1) {
            line = 0;
            row++;
        } else {
            line++;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2169966.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于单片机的温湿度检测判断系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机&#xff0c;采用dht11温湿度传感器检测温湿度&#xff0c; 通过lcd1602显示屏各个参数&#xff0c;四个按键分别可以增加温湿度的阈值&#xff0c; 如果超过阈值&#xff0c;则…

BaseCTF2024 web

Web [Week1] HTTP 是什么呀 GET: ?basectf%77%65%31%63%25%30%30%6d%65POST: BaseflgX-Forwarded-For:127.0.0.1Referer: BaseCookie: c00k13i cant eat itUser-Agent: Base有Location跳转, 抓包得到flag: QmFzZUNURntkZGUzZjA0Yy1hMDg5LTQwNGMtOTFjNi01ODZjMzAxMzM3Y2J9Cg…

解锁创意新纪元:Stable Diffusion绘画技术的非凡优势

Stable Difusion 是一款从文本到图像的潜在扩散模型&#xff0c;其操作界面如图所示。该模型由初创公司Stabiity A1、慕尼黑大学机器视觉与学习小组以及神经网络视频公司Runway 合作研发&#xff0c;首次发布于2022年8月&#xff0c;而在同年11月更新的2.0版本更是给用户带来了…

“给领导买饭”,刺痛打工人

帮领导办私事&#xff0c;你会接受还是拒绝&#xff1f; 转载&#xff1a;定焦&#xff08;dingjiaoone&#xff09;原创 作者 | 艾乐伊 郑浩钧 苏琦 王璐 编辑 | 苏琦 打工人最讨厌的事&#xff0c;领导喊你帮他带饭带娃&#xff0c;算一件。 近日&#xff0c;上海某教培公司…

fuzzer实战-magma-模糊测试

Getting Started | magma首先打开这个链接&#xff0c;跟着官网指导做&#xff1a; 并且参考Titan的官网使用方法&#xff1a;GitHub - 5hadowblad3/Titan: Research artifact for Oakland (S&P) 2024, "Titan: Efficient Multi-target Directed Greybox Fuzzing&quo…

Rce脚本自动化amp;批量

这里放上一篇我学生的投稿文章 0x00 前言 在现代网络安全领域&#xff0c;远程代码执行&#xff08;RCE&#xff09;漏洞的发现与利用成为了重要的研究课题。随着攻击手段的不断演进&#xff0c;安全专业人士面临着日益复杂的威胁环境。为应对这一挑战&#xff0c;自动化和批…

ChatGPT Sidebar 浏览器插件配置指南

随着聊天机器人技术的不断进步&#xff0c;越来越多的人开始依赖这些强大的工具来提高工作效率、获取信息和解决问题。OpenAI 的 ChatGPT 是其中最受欢迎的聊天机器人之一。为了方便用户在浏览网页时随时与 ChatGPT 互动&#xff0c;开发者们设计了一款名为 ChatGPT Sidebar 的…

30+程序员顶着被裁员的压力,为什么选择从零开始:转行大模型?

在当今这个科技进步迅速的时代&#xff0c;程序员作为引领技术革新的关键角色&#xff0c;正处于一个既充满机会又面临挑战的关键时刻。随着人工智能、大数据处理、云服务等领域的迅猛发展&#xff0c;大型模型&#xff08;例如GPT系列、BERT等&#xff09;已经成为行业内的热议…

【07】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-Swiper轮播组件与样式结构重用

序言&#xff1a; 本文详细讲解了关于我们在页面上经常看到的轮播图在鸿蒙开发中如何用Swiper实现&#xff0c;介绍了Swiper的基本用法与属性&#xff0c;及如何面对大段的重复代码进行封装和重用&#xff08;Extend、Styles、Builder&#xff09;&#xff0c;使代码更加简洁易…

HarmonyOS鸿蒙开发实战( Beta5.0)标题下拉缩放实践案例

鸿蒙HarmonyOS NEXT开发实战往期文章必看&#xff08;持续更新......&#xff09; HarmonyOS NEXT应用开发性能实践总结 HarmonyOS NEXT应用开发案例实践总结合集 最新版&#xff01;“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门…

耦合微带线单元的网络参量和等效电路公式推导

文档下载链接&#xff1a;耦合微带线单元的网络参量和等效电路资源-CSDN文库https://download.csdn.net/download/lu2289504634/89583027笔者水平有限&#xff0c;错误之处欢迎留言&#xff01; 一、耦合微带线奇偶模详细推导过程 二、2,4端口开路 三、2端口短路、3端口开路 四…

护眼台灯哪个品牌更好?五款由专业眼科医生推荐的护眼台灯

台灯是每个家庭中不可或缺的照明设备&#xff0c;尤其是对于有学龄儿童的家庭来说&#xff0c;孩子们每天在家学习和做作业时&#xff0c;一款优秀的护眼台灯显得尤为重要。如果长期使用的台灯是不合格&#xff0c;不能给孩子提供一个好的光照环境&#xff0c;那么孩子们的视力…

VUE.js笔记

1.介绍vue Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。无论是简单还是复杂的界面&#xff0c;Vue 都可以胜任。 Vue 应用程序的基本…

镭射限高防外破预警装置-线路防外破可视化监控,安全尽在掌握中

镭射限高防外破预警装置-线路防外破可视化监控&#xff0c;安全尽在掌握中 在城市化浪潮的汹涌推进中&#xff0c;电力如同现代社会的生命之脉&#xff0c;其安全稳定运行直接关系到每一个人的生活质量和社会的整体发展。然而&#xff0c;随着建设的加速&#xff0c;电力设施通…

宠物店揭秘!那种猫罐头好?4款营养满分主食罐头来袭

五年来&#xff0c;我家宠物店始终秉持初心&#xff0c;为猫咪打造了一个美食乐园&#xff0c;从湿猫粮、干猫粮&#xff0c;到各式零食&#xff0c;应有尽有。最近&#xff0c;猫罐头这股热潮更是席卷而来&#xff0c;成为许多猫咪的新宠。然而&#xff0c;面对市场上各式各样…

C语言课程设计题目四:实验设备管理系统设计

序号系统设计题目进度1职工信息管理系统设计已完成&#xff0c;在本专栏2图书信息管理系统设计已完成&#xff0c;在本专栏3图书管理系统设计已完成&#xff0c;在本专栏4实验设备管理系统设计已完成&#xff0c;在本专栏5西文下拉菜单的设计链接6学生信息管理系统设计链接7学生…

Spring Boot入门全攻略:从环境搭建到项目运行,一步步带你走进高效Java开发的奇妙世界!

Spring Boot 是一个简化 Spring 应用开发的框架&#xff0c;它提供了一种快速、广泛接受的平台&#xff0c;用于创建独立的、生产级的基于 Spring 的应用。以下是一个简单的 Spring Boot 入门教程。 1. 环境准备 Java&#xff1a;确保安装了 Java 8 或更高版本。Maven/Gradle&…

【微信小程序】uniapp中HBuilder修改代码,微信开发者工具没有刷新

方法一&#xff1a;设置-编辑器-按图设置&#xff0c;去掉【修改文件时自动保存】 方法二&#xff1a;开启热加载 方法三&#xff1a;直接HBuilder中用在运行

c语言200例 64

大家好&#xff0c;欢迎来到无限大的频道。 今天带领大家来学习c语言。 题目要求&#xff1a; 设计一个进行候选人的选票程序。假设有三位候选人&#xff0c;在屏幕上输入要选择的候选人姓名&#xff0c; 有10次投票机会&#xff0c;最后输出每个人的得票结果。好的&#xff…

在线聊天室项目(Vue3 + SpringBoot)

目录 项目描述 技术栈选型 项目开发过程文档 项目页面效果 项目源码地址 项目描述 1. 网页在线聊天室&#xff0c;实现了群组系统和好友系统&#xff0c;因此项目可以在公共群组&#xff0c;私有群组和私人之间进行聊天。 2. 项目主要使用Websocket实时通信技术实现聊天&…