ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JAVA——构建FAT32文件系统的DBR(DOS引导记录)类

2020-12-29 22:00:22  阅读:230  来源: 互联网

标签:JAVA 字节 FAT32 扇区 final static DOS Byte public


Maven

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

解决方案

DMR 

package cn.edu.zstu.fms.storage;

import lombok.Data;

/**
 * 是DOS引导记录,也称为操作系统引导记录,在DBR之后往往会有一些保留扇区。
 * @see <a href="https://blog.51cto.com/dengqi/1349327">FAT32文件系统详解</a>
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-12-29 18:28
 */
@Data
public class DOSBootRecord {
    /**
     * 跳转指令 开始字节位置
     */
    public static final int JUMP_COMMAND_START =0;
    /**
     * 跳转指令 长度
     */
    public static final int JUMP_COMMAND_LENGTH =2;
    /**
     * OEM代号 开始字节位置
     */
    public static final int OEM_CODE_START =3;
    /**
     * OEM代号 长度
     */
    public static final int OEM_CODE_LENGTH =8;
    /**
     * BPB 开始字节位置
     */
    public static final int BIOS_PARAMETER_BLOCK_START = 11;
    /**
     * BPB 长度
     */
    public static final int BIOS_PARAMETER_BLOCK_LENGTH =79;
    /**
     * 引导程序代码 开始字节位置
     */
    public static final int BOOTLOADER_CODE_START = 90;
    /**
     * 引导程序代码 长度
     */
    public static final int BOOTLOADER_CODE_LENGTH =420;
    /**
     * BPB 开始字节位置
     */
    public static final int END_SIGN_START = 510;
    /**
     * 结束标志 长度
     */
    public static final int END_SIGN_LENGTH =2;
    /**
     * 源数据
     */
    private byte[] source;

    /**
     * 跳转指令
     * 占2字节,它将程序执行流程跳转到引导程序处。
     * 跳转指令后,一条空的指令NOP(90H)
     * @see <a href="https://blog.csdn.net/pnzrk/article/details/88943746">FAT32</a>
     */
    private byte[] jumpCommand = new byte[2];

    /**
     * OEM代号
     * 占8字节,其内容由创建该文件系统的OEM厂商具体安排。
     */
    private byte[] oemCode = new byte[8];

    /**
     * BPB BIOS参数块
     * BIOS Parameter Block
     * FAT32的BPB从DBR的第12个字节开始,占用79字节,记录了有关该文件系统的重要信息
     */
    private BIOSParameterBlock biosParameterBlock;

    /**
     * 引导程序代码
     * FAT32的DBR引导程序占用420字节,对于没有安装操作系统的分区来说这段程序是没有用处的。
     */
    private byte[] bootloaderCode = new byte[420];

    /**
     * 结束标志
     * 0xAA55
     */
    private byte[] endSign = new byte[2];

    /**
     *
     * @param source
     */
    public DOSBootRecord(byte[] source){
        this.source = source;
        //跳转指令
        jumpCommand = new byte[JUMP_COMMAND_LENGTH];
        System.arraycopy(this.source, JUMP_COMMAND_START, jumpCommand, 0, JUMP_COMMAND_LENGTH);
        //OEM代号
        oemCode = new byte[OEM_CODE_LENGTH];
        System.arraycopy(this.source, OEM_CODE_START, oemCode, 0, OEM_CODE_LENGTH);
        //BIOS参数块
        byte[] biosParameterBlockSource = new byte[BIOS_PARAMETER_BLOCK_LENGTH];
        System.arraycopy(this.source, BIOS_PARAMETER_BLOCK_START, biosParameterBlockSource, 0, BIOS_PARAMETER_BLOCK_LENGTH);
        this.biosParameterBlock = new BIOSParameterBlock(biosParameterBlockSource);
        //引导程序代码
        bootloaderCode = new byte[BOOTLOADER_CODE_LENGTH];
        System.arraycopy(this.source, BOOTLOADER_CODE_START, bootloaderCode, 0, BOOTLOADER_CODE_LENGTH);
        //结束标志
        endSign = new byte[END_SIGN_LENGTH];
        System.arraycopy(this.source, END_SIGN_START, endSign, 0, END_SIGN_LENGTH);
    }
}

BPB 

package cn.edu.zstu.fms.storage;

import lombok.Data;

import java.io.Serializable;
import java.nio.charset.Charset;

/**
 * BIOS参数块
 * BIOS Parameter Block
 * FAT32的BPB从DBR的第12个字节开始,占用79字节,记录了有关该文件系统的重要信息
 * @see <a href="https://blog.csdn.net/pnzrk/article/details/88943746">FAT32</a>
 * @author ShenTuZhiGang
 * @version 1.0.0
 * @date 2020-12-29 19:23
 */
@Data
public class BIOSParameterBlock implements Serializable {
    /*
     *  字节偏移
     */
    /**
     * 每扇区字节数 字节偏移
     */
    public static final Byte SECTOR_BYTE_NUM_OFFSET_POSITION = 0x0B - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 每簇扇区数 字节偏移
     */
    public static final Byte CLUSTER_SECTOR_NUM_OFFSET_POSITION = 0x0D - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * DOS保留扇区数 字节偏移
     */
    public static final Byte DOS_RESERVED_SECTOR_NUM_OFFSET_POSITION = 0x1E - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * FAT个数 字节偏移
     */
    public static final Byte FILE_ALLOCATION_TABLE_NUM_OFFSET_POSITION = 0x10 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 未用 字节偏移
     */
    public static final Byte UNUSED_1_OFFSET_POSITION = 0x11 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 未用 字节偏移
     */
    public static final Byte UNUSED_2_OFFSET_POSITION = 0x13 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 介质描述符 字节偏移
     */
    public static final Byte MEDIA_DESCRIPTOR_OFFSET_POSITION = 0x15 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 未用 字节偏移
     */
    public static final Byte UNUSED_3_OFFSET_POSITION = 0x16 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 每磁道扇区数 字节偏移
     */
    public static final Byte TRACK_SECTOR_NUM_OFFSET_POSITION = 0x18 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 磁头数 字节偏移
     */
    public static final Byte HEAD_NUM_OFFSET_POSITION = 0x1A - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 隐藏扇区数 字节偏移
     */
    public static final Byte HIDDEN_SECTOR_OFFSET_POSITION = 0x1C - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 分区扇区总数 字节偏移
     */
    public static final Byte PARTITION_SECTOR_NUM_OFFSET_POSITION = 0x20 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;

    /*
     * 扩展BPB
     */

    /**
     * 每FAT扇区数 字节偏移
     */
    public static final Byte FAT_SECTOR_NUM_OFFSET_POSITION = 0x24 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 标记 字节偏移
     */
    public static final Byte SIGN_OFFSET_POSITION = 0x28 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 版本 字节偏移
     */
    public static final Byte VERSION_OFFSET_POSITION = 0x2A - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 根目录首簇号 字节偏移
     */
    public static final Byte ROOT_CLUSTER_NUMBER_OFFSET_POSITION = 0x2C - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 文件系统信息扇区号 字节偏移
     */
    public static final Byte FILE_SYSTEM_INFORMATION_SECTOR_NUMBER_OFFSET_POSITION = 0x30 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * DBR备份扇区号 字节偏移
     */
    public static final Byte BACKUP_SECTOR_NUMBER_OFFSET_POSITION = 0x32 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 保留 字节偏移
     */
    public static final Byte RETAIN_OFFSET_POSITION = 0x34 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * BIOS驱动器号 字节偏移
     */
    public static final Byte bios_Drive_Number_OFFSET_POSITION = 0x40 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 未用 字节偏移
     */
    public static final Byte extend_Boot_Flag_OFFSET_POSITION = 0x41 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 扩展引导标记 字节偏移
     */
    public static final Byte UNUSED_4_OFFSET_POSITION = 0x42 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 卷序列号 字节偏移
     */
    public static final Byte VOLUME_SERIAL_NUMBER_OFFSET_POSITION = 0x43 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 卷标 字节偏移
     */
    public static final Byte VOLUME_LABEL_OFFSET_POSITION = 0x47 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;
    /**
     * 文件系统类型 字节偏移
     */
    public static final Byte FILE_SYSTEM_TYPE_OFFSET_POSITION = 0x52 - DOSBootRecord.BIOS_PARAMETER_BLOCK_START;

    /*
     *   长度
     */

    /**
     * 每扇区字节数 长度
     */
    public static final Byte SECTOR_BYTE_NUM_LENGTH = 2;
    /**
     * 每簇扇区数 长度
     */
    public static final Byte CLUSTER_SECTOR_NUM_LENGTH = 1;
    /**
     * DOS保留扇区数 长度
     */
    public static final Byte DOS_RESERVED_SECTOR_NUM_LENGTH = 2;
    /**
     * FAT个数 长度
     */
    public static final Byte FILE_ALLOCATION_TABLE_NUM_LENGTH = 1;
    /**
     * 未用 长度
     */
    public static final Byte UNUSED_1_LENGTH = 2;
    /**
     * 未用 长度
     */
    public static final Byte UNUSED_2_LENGTH = 2;
    /**
     * 介质描述符 长度
     */
    public static final Byte MEDIA_DESCRIPTOR_LENGTH = 1;
    /**
     * 未用 长度
     */
    public static final Byte UNUSED_3_LENGTH = 2;
    /**
     * 每磁道扇区数 长度
     */
    public static final Byte TRACK_SECTOR_NUM_LENGTH = 2;
    /**
     * 磁头数 长度
     */
    public static final Byte HEAD_NUM_LENGTH = 2;
    /**
     * 隐藏扇区数 长度
     */
    public static final Byte HIDDEN_SECTOR_LENGTH = 4;
    /**
     * 分区扇区总数 长度
     */
    public static final Byte PARTITION_SECTOR_NUM_LENGTH = 4;

    /*
     * 扩展BPB
     */

    /**
     * 每FAT扇区数 长度
     */
    public static final Byte FAT_SECTOR_NUM_LENGTH = 4;
    /**
     * 标记 长度
     */
    public static final Byte SIGN_LENGTH = 2;
    /**
     * 版本 长度
     */
    public static final Byte VERSION_LENGTH = 2;
    /**
     * 根目录首簇号 长度
     */
    public static final Byte ROOT_CLUSTER_NUMBER_LENGTH = 4;
    /**
     * 文件系统信息扇区号 长度
     */
    public static final Byte FILE_SYSTEM_INFORMATION_SECTOR_NUMBER_LENGTH = 2;
    /**
     * DBR备份扇区号 长度
     */
    public static final Byte BACKUP_SECTOR_NUMBER_LENGTH = 2;
    /**
     * 保留 长度
     */
    public static final Byte RETAIN_LENGTH = 12;
    /**
     * BIOS驱动器号 长度
     */
    public static final Byte bios_Drive_Number_LENGTH = 1;
    /**
     * 未用 长度
     */
    public static final Byte extend_Boot_Flag_LENGTH = 1;
    /**
     * 扩展引导标记 长度
     */
    public static final Byte UNUSED_4_LENGTH = 1;
    /**
     * 卷序列号 长度
     */
    public static final Byte VOLUME_SERIAL_NUMBER_LENGTH = 4;
    /**
     * 卷标 长度
     */
    public static final Byte VOLUME_LABEL_LENGTH = 11;
    /**
     * 文件系统类型 长度
     */
    public static final Byte FILE_SYSTEM_TYPE_LENGTH = 8;

    /**
     * 源数据
     */
    private byte[] source;

    /**
     * 每扇区字节数
     * 字节偏移 0x0B
     * 长度 2个字节
     * 记录每个逻辑扇区的大小,其常见的值为512,但是并不是固定的值。
     * 该值可以由程序定义,合法值包括512、1024、2048、4096。
     */
    private Short sectorByteNum;

    /**
     * 每簇扇区数
     * 字节偏移 0x0D
     * 长度 1个字节
     * 记录着文件系统的簇大小,即由多少个扇区组成一个簇。
     * 簇是FAT12,FAT16及FAT32文件系统下数据的最小存储单元,
     * 一个簇由一组连续的扇区组成,簇所含的扇区数必须是2的整数次幂,
     * 如1,2,4,8,16,32,64,128.
     * 在Windows 2000以前族最大值为64扇区,之后最大值为128。
     * 在FAT文件系统中,所有的簇是从2开始编号,
     * 每个簇都有一个自己的地址编号,
     * 但是所有的簇都位于数据区,在数据区之前没有簇。
     */
    private Byte clusterSectorNum;

    /**
     * DOS保留扇区数
     * 字节偏移 0x0E
     * 长度 1个字节
     * DBR到FAT1表之间的扇区数,或者说是FAT1的开始扇区号,对于FAT32文件系统来说,该值的范围是32扇区到38扇区之间。
     */
    private Short dosReservedSectorNum;

    /**
     * FAT个数
     * 字节偏移 0x10
     * 长度 1个字节
     * 一般为2
     */
    private Byte FATNum;

    /**
     * 介质描述符
     * 字节偏移 0x15
     * 长度 1个字节
     * 描述磁盘介质的参数,根据磁盘性质的不同,取不同的值。0xF8标准值,可移动存储介质,常用 0xF0
     */
    private Byte mediaDescriptor;

    /**
     * 每磁道扇区数
     * 字节偏移 0x18
     * 长度 1个字节
     * 一般其值为63
     */
    private Short trackSectorNum;

    /**
     * 磁头数
     * 字节偏移 0x1A
     * 长度 1个字节
     * 一般为255
     */
    private Short headNum;

    /**
     * 隐藏扇区数
     * 字节偏移 0x1C
     * 长度 1个字节
     * 是MBR到DBR之间的扇区数,对于扩展分区中逻辑驱动顺来说,是其EBR到DBR。可以为0。
     */
    private Integer hiddenSector;

    /**
     * 分区扇区总数
     * 字节偏移 0x20
     * 长度 4个字节
     * 分区的总扇区数,也就是FAT32分区的大小
     */
    private Integer partitionSectorNum;

    /*
     * 扩展BPB
     */


    /**
     * 每FAT扇区数
     * 字节偏移 0x24
     * 长度 1个字节
     * FAT表占用扇区数
     */
    private Integer FATSectorNum;

    /**
     * 标记
     * 字节偏移 0x28
     * 长度 1个字节
     * FAT32是否可用,2为可用,此域FAT32 特有
     */
    private Short sign;

    /**
     * 版本
     * 字节偏移 0x2A
     * 长度 1个字节
     * FAT32版本号0.0,FAT32特有
     */
    private Short version;

    /**
     * 根目录首簇号
     * 字节偏移 0x2C
     * 长度 4个字节
     * 分区在格式化的时候,
     * 格式化程序会在数据区中指派一个簇作为FAT32的根目录的开始,并把该簇号记录在BPB中。
     * 通常都是把数据区中的第一簇分配给根目录使用,也就是2号簇。
     */
    private Integer rootClusterNumber;

    /**
     * 文件系统信息扇区号
     * 字节偏移 0x30
     * 长度 2个字节
     * FAT32文件系统在DBR的保留扇区中安排了一个文件系统信息扇区,用以记录数据区中空闲簇的数量及下一个可用的空闲簇的簇号,
     * 该扇区一般在分区的1号扇区,也就是紧跟在DBR之后的一个扇区。
     * FSINFO(文件系统信息扇区)扇区号1,该扇区为操作系统提供关于空簇总数及下一可用簇的信息
     */
    private Short fileSystemInformationSectorNumber;

    /**
     * DBR备份扇区号
     * 字节偏移 0x32
     * 长度 2个字节
     * FAT32文件系统在DBR的保留扇区中安排了一个DBR的备份,
     * 一般在6号扇区,也就是分区的第7个扇区,该备份扇区与原DBR扇区的内容完全一样,如果原DBR遭到破坏,可以用备份扇区号修复。
     */
    private Short backupSectorNumber;

    /**
     * BIOS驱动器号
     * 字节偏移 0x40
     * 长度 1个字节
     * 这是BIOS的INT 13H所描述的设备号码,一般硬盘为80H,一般软盘为00H等
     */
    private Byte biosDriveNumber;

    /**
     * 扩展引导标记
     * 字节偏移 0x41
     * 长度 1个字节
     * 用来确认后面的三个参数是否有效,FAT为29H
     */
    private Byte extendBootFlag;

    /**
     * 卷序列号
     * 字节偏移 0x43
     * 长度 4个字节
     * 磁盘序列号,通常为一随机数
     */
    private Integer volumeSerialNumber;

    /**
     * 卷标
     * 字节偏移 0x47 {@link cn.edu.zstu.fms.storage.BIOSParameterBlock#VOLUME_LABEL_OFFSET_POSITION }
     * 长度 11个字节 {@link cn.edu.zstu.fms.storage.BIOSParameterBlock#VOLUME_LABEL_LENGTH }
     * 用户设置的卷标ASCII,如果没有则4E 4F 20 4E 41 4D 45 20 20 20 20 即NO NAME。如果建立文件系统的时候指定了卷标,会保存在此
     */
    private Character[] volumeLabel;

    /**
     * 文件系统类型
     * 字节偏移 0x52 {@link cn.edu.zstu.fms.storage.BIOSParameterBlock#FILE_SYSTEM_TYPE_OFFSET_POSITION }
     * 长度 8个字节 {@link cn.edu.zstu.fms.storage.BIOSParameterBlock#FILE_SYSTEM_TYPE_LENGTH }
     * 使用ASCII码记录当前分区的文件系统类型,46 41 54 33 32 20 20 20即FAT32
     */
    private Character[] fileSystemType;
    /**
     *
     * @param source
     */
    public BIOSParameterBlock(byte[] source){
        this.source = source;
    }
}


class ByteUtil {
    public static byte[] getBytes(short data) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data & 0xff00) >> 8);
        return bytes;
    }

    public static byte[] getBytes(char data) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (data);
        bytes[1] = (byte) (data >> 8);
        return bytes;
    }

    public static byte[] getBytes(int data) {
        byte[] bytes = new byte[4];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data & 0xff00) >> 8);
        bytes[2] = (byte) ((data & 0xff0000) >> 16);
        bytes[3] = (byte) ((data & 0xff000000) >> 24);
        return bytes;
    }

    public static byte[] getBytes(long data) {
        byte[] bytes = new byte[8];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data >> 8) & 0xff);
        bytes[2] = (byte) ((data >> 16) & 0xff);
        bytes[3] = (byte) ((data >> 24) & 0xff);
        bytes[4] = (byte) ((data >> 32) & 0xff);
        bytes[5] = (byte) ((data >> 40) & 0xff);
        bytes[6] = (byte) ((data >> 48) & 0xff);
        bytes[7] = (byte) ((data >> 56) & 0xff);
        return bytes;
    }

    public static byte[] getBytes(float data) {
        int intBits = Float.floatToIntBits(data);
        return getBytes(intBits);
    }

    public static byte[] getBytes(double data) {
        long intBits = Double.doubleToLongBits(data);
        return getBytes(intBits);
    }

    public static byte[] getBytes(String data, String charsetName) {
        Charset charset = Charset.forName(charsetName);
        return data.getBytes(charset);
    }

    public static byte[] getBytes(String data) {
        return getBytes(data, "UTF-8");
    }


    public static short getShort(byte[] bytes) {
        return (short) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
    }

    public static char getChar(byte[] bytes) {
        return (char) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
    }

    public static int getInt(byte[] bytes) {
        return (0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)) | (0xff0000 & (bytes[2] << 16)) | (0xff000000 & (bytes[3] << 24));
    }

    public static long getLong(byte[] bytes) {
        return(0xffL & (long)bytes[0]) | (0xff00L & ((long)bytes[1] << 8)) | (0xff0000L & ((long)bytes[2] << 16)) | (0xff000000L & ((long)bytes[3] << 24))
                | (0xff00000000L & ((long)bytes[4] << 32)) | (0xff0000000000L & ((long)bytes[5] << 40)) | (0xff000000000000L & ((long)bytes[6] << 48)) | (0xff00000000000000L & ((long)bytes[7] << 56));
    }

    public static float getFloat(byte[] bytes) {
        return Float.intBitsToFloat(getInt(bytes));
    }

    public static double getDouble(byte[] bytes) {
        long l = getLong(bytes);
        System.out.println(l);
        return Double.longBitsToDouble(l);
    }

    public static String getString(byte[] bytes, String charsetName) {
        return new String(bytes, Charset.forName(charsetName));
    }

    public static String getString(byte[] bytes) {
        return getString(bytes, "UTF-8");
    }
}

参考文章

FAT32

FAT32文件系统详解

javadoc中{@link}与@see的简单使用以及区别

FAT32文件系统快速入门

FAT32文件系统结构详解

标签:JAVA,字节,FAT32,扇区,final,static,DOS,Byte,public
来源: https://blog.csdn.net/weixin_43272781/article/details/111937905

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有