⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatfs.java

📁 java 编写的一个FAT16读写源代码 支持长文件名和子目录
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
    }

    public long getOffset(Object fd) throws IOException
    {
        synchronized (lock)
        {
            return ((FATFSDescriptor)fd).filePointer;
        }
    }

    public long getLength(Object fd) throws IOException
    {
        synchronized (lock)
        {
            return ((FATFSDescriptor)fd).length;
        }
    }

    public int available(Object fd) throws IOException
    {
        FATFSDescriptor fDesc = (FATFSDescriptor)fd;
        synchronized (lock)
        {
            return fDesc.length - fDesc.filePointer;
        }
    }

    public void close(Object fd) throws IOException
    {
        FATFSDescriptor fDesc = (FATFSDescriptor)fd;
        synchronized (lock)
        {
            if((openWriters != null) && openWriters.contains(fd))
            {
                synchronized (sector)
                {
                    if(!disk.read((fDesc.fileSector << shiftBytesPerSector) + fDesc.fileOffset, sector, 0, DIR_ENTRY_SIZE))
                    {
                        throw new IOException("Unable to read disk");
                    }

                    long millis = System.currentTimeMillis();
                    if(calendar == null)
                    {
                       calendar = Calendar.getInstance();
                    }
                    calendar.setTime(new Date(millis));
                    int time = ((calendar.get(Calendar.SECOND) / 2) & 0x01F) |
                               ((calendar.get(Calendar.MINUTE) & 0x03F) << 5) |
                               ((calendar.get(Calendar.HOUR_OF_DAY) & 0x1F) << 11);
                    int date = (calendar.get(Calendar.DATE) & 0x1F) |
                               (((calendar.get(Calendar.MONTH) + 1) & 0x0F) << 5) |
                               (((calendar.get(Calendar.YEAR) - 1980) & 0x7F) << 9);

                    ArrayUtils.putShort(date, sector, OFFSET_DIR_LAST_ACCESS_DATE);
                    ArrayUtils.putShort(time, sector, OFFSET_DIR_WRITE_TIME);
                    ArrayUtils.putShort(date, sector, OFFSET_DIR_WRITE_DATE);
                    ArrayUtils.putInt(fDesc.length, sector, OFFSET_DIR_FILE_SIZE);

                    disk.write((fDesc.fileSector << shiftBytesPerSector) + fDesc.fileOffset, sector, 0, DIR_ENTRY_SIZE);
                }

                openWriters.removeElement(fd);
            }
        }
    }

    public void unmount()
    {
        disk.flush();
        return; /*TODO*/
    }

    public byte[] getContents(String fileName, byte uid) throws IOException {return null; /*TODO*/}










    private static final int FAT16_MASK = 0x0FFFF;
    private static final int FAT32_MASK = 0x0FFFFFFF;

    private static final int FS_TYPE_FAT32 = 0;
    private static final int FS_TYPE_FAT16 = 1;
    private static final int FS_TYPE_FAT12 = 2;

    private static final int CLUST_EOFE = 0xffffffff;

    private static final int OFFSET_FAT_SIGNATURE = 510;
    private static final int OFFSET_BPB_BYTES_PER_SECTOR = 11;
    private static final int OFFSET_BPB_SECTORS_PER_CLUSTER = 13;
    private static final int OFFSET_BPB_RESERVED_SECTOR_COUNT = 14;
    private static final int OFFSET_BPB_NUM_FATS = 16;
    private static final int OFFSET_BPB_ROOT_ENTRY_COUNT = 17;
    private static final int OFFSET_BPB_TOTAL_SECTORS_16 = 19;
    private static final int OFFSET_BPB_FAT_SIZE_16 = 22;
    private static final int OFFSET_BPB_TOTAL_SECTORS_32 = 32;
    private static final int OFFSET_BPB_FAT_SIZE_32 = 36;

    private static final int ATTR_READ_ONLY = 0x01;
    private static final int ATTR_HIDDEN =    0x02;
    private static final int ATTR_SYSTEM =    0x04;
    private static final int ATTR_VOLUME_ID = 0x08;
    private static final int ATTR_DIRECTORY = 0x10;
    private static final int ATTR_ARCHIVE =   0x20;
    private static final int ATTR_LONG_NAME = ATTR_READ_ONLY |
                                              ATTR_HIDDEN |
                                              ATTR_SYSTEM |
                                              ATTR_VOLUME_ID;

    private static final int DIR_ENTRY_SIZE =                32;
    private static final int OFFSET_DIR_NAME =                0;
    private static final int OFFSET_DIR_ATTRIBUTES =         11;
    private static final int OFFSET_DIR_NT_RESERVED =        12;
    private static final int OFFSET_DIR_CREATE_TIME_TENTH =  13;
    private static final int OFFSET_DIR_CREATE_TIME =        14;
    private static final int OFFSET_DIR_CREATE_DATE =        16;
    private static final int OFFSET_DIR_LAST_ACCESS_DATE =   18;
    private static final int OFFSET_DIR_FIRST_CLUSTER_HIGH = 20;
    private static final int OFFSET_DIR_WRITE_TIME =         22;
    private static final int OFFSET_DIR_WRITE_DATE =         24;
    private static final int OFFSET_DIR_FIRST_CLUSTER_LOW =  26;
    private static final int OFFSET_DIR_FILE_SIZE =          28;

    private static final int DIR_SLOT_DELETED = 0xE5;
    private static final int DIR_LAST_ENTRY =   0x00;
    private static final int DIR_NAME_IS_E5 =   0x05;












    private DiskInterface disk;

    //Buffer we will use for all sector reads and writes.  This will save unnecessary memory allocations.
    private byte[] sector;
    //Secondary buffer we will use for reads and writes to the FAT table.  This will save unnecessary memory allocations.
    private byte[] sector2;

    //Addresses to the start of each File Allocation Table (most FS use two copies, but there could be more)
    private int[] tableAddresses;
    private int bytesPerSector;
    private int shiftBytesPerSector;
    private int sectorsPerCluster;
    private int shiftSectorsPerCluster;
    private int FATType;
    private int firstDataSector;
    private int firstRootDirSector;
    private int maxCluster;

    private String[] fileParts = new String[10];
    private int filePartsLength = 0;

    private int currentFileSector;
    private int currentFileOffset;

    private Object lock = new Object();
    private Vector listVector = null;

    private Calendar calendar = null;
    
    private Vector openReaders = null;
    private Vector openWriters = null;

    private static final byte[] dotBytes = {'.', ' ', ' ',  ' ',  ' ',  ' ',  ' ',  ' ',  ' ',  ' ',  ' '};
    private static final byte[] dotdotBytes = {'.', '.', ' ',  ' ',  ' ',  ' ',  ' ',  ' ',  ' ',  ' ',  ' '};

    private void parseBootSector(byte[] sector) throws FATException
    {
        if(ArrayUtils.getShort(sector, OFFSET_FAT_SIGNATURE) != 0x0AA55)
        {
            throw new FATException("Invalid FAT signature");
        }

        int totalSectors = ArrayUtils.getShort(sector, OFFSET_BPB_TOTAL_SECTORS_16);
        if(totalSectors == 0)
        {
            totalSectors = ArrayUtils.getInt(sector, OFFSET_BPB_TOTAL_SECTORS_32);
        }
        if((totalSectors << shiftBytesPerSector) > disk.size())
        {
            throw new FATException("Boot sector shows disk larger than it really is");
        }
        bytesPerSector = ArrayUtils.getShort(sector, OFFSET_BPB_BYTES_PER_SECTOR);
        if(bytesPerSector == 0)
        {
            throw new FATException("Bytes per sector cannot be 0.");
        }
        int x = bytesPerSector;
        shiftBytesPerSector = 0;
        while(x != 1)
        {
            shiftBytesPerSector++;
            x >>= 1;
        }

        sectorsPerCluster = ArrayUtils.getByte(sector, OFFSET_BPB_SECTORS_PER_CLUSTER);
        if(sectorsPerCluster == 0)
        {
            throw new FATException("Secotrs per cluster cannot be 0.");
        }
        x = sectorsPerCluster;
        shiftSectorsPerCluster = 0;
        while(x != 1)
        {
            shiftSectorsPerCluster++;
            x >>= 1;
        }

        int rootEntCnt = ArrayUtils.getShort(sector, OFFSET_BPB_ROOT_ENTRY_COUNT);
        int rootDirSectors = ((rootEntCnt * DIR_ENTRY_SIZE) + (bytesPerSector - 1)) / bytesPerSector;

        int fatSize = ArrayUtils.getShort(sector, OFFSET_BPB_FAT_SIZE_16);
        if(fatSize == 0)
        {
            fatSize = ArrayUtils.getInt(sector, OFFSET_BPB_FAT_SIZE_32);
        }

        int reservedSectorCount = ArrayUtils.getShort(sector, OFFSET_BPB_RESERVED_SECTOR_COUNT);

        int numFATs = ArrayUtils.getByte(sector, OFFSET_BPB_NUM_FATS);

        firstRootDirSector = reservedSectorCount + (numFATs * fatSize);
        firstDataSector = firstRootDirSector + rootDirSectors;

        int dataSectors = totalSectors - firstDataSector;
        int countOfClusters = dataSectors >> shiftSectorsPerCluster;
        maxCluster = countOfClusters + 2;

        if(countOfClusters < 4085)
        {
            FATType = FS_TYPE_FAT12;
            throw new FATException("FAT12 is not supported");
        }
        else if(countOfClusters < 65525)
        {
            FATType = FS_TYPE_FAT16;
        }
        else
        {
            FATType = FS_TYPE_FAT32;
        }

        tableAddresses = new int[numFATs];

        for(int i = 0; i < numFATs; i++)
        {
            tableAddresses[i] = (reservedSectorCount + (i * fatSize)) * bytesPerSector;
        }
    }

    private int sectorToCluster(int sector)
    {
	    return (((sector - firstDataSector) >> shiftSectorsPerCluster) + 2);
    }

    private int clusterToSector(int cluster)
    {
        return ((cluster - 2) << shiftSectorsPerCluster) + firstDataSector;
    }

    private int nextCluster(int cluster, boolean growFile, boolean clearNew) throws FATException
    {
        int mask;

        // Get the next cluster pointer.
        int next = readFATEntry(cluster);

        if(FATType == FS_TYPE_FAT32)
        {
            mask = FAT32_MASK;
        }
        else if(FATType == FS_TYPE_FAT16)
        {
            mask = FAT16_MASK;
        }
        else
        {
            throw new FATException("Unrecognized FAT Type");
        }

        if(next == (CLUST_EOFE & mask))
        {
            // We're at the end of the chain.
            if(growFile)
            {
                boolean emptyClusterFound = false;

                // Look for an unused cluster.
                for(next = 2; next < maxCluster; next++)
                {
                    int temp = readFATEntry(next);
                    if(temp == 0)
                    {
                        // Found an unused cluster, add it to the end of the chain.
                        writeFATEntry(cluster, next);
                        writeFATEntry(next, CLUST_EOFE);
                        emptyClusterFound = true;

                        if(clearNew)
                        {
                            synchronized (sector2)
                            {
                                int newSector = clusterToSector(next);

                                com.dalsemi.system.ArrayUtils.arrayFill(sector2, 0, bytesPerSector, (byte)0x00);
                                for(int i = 0; i < sectorsPerCluster; i++)
                                {
                                    disk.write((newSector + i) << shiftBytesPerSector, sector2, 0, bytesPerSector);
                                }
                            }
                        }
                        break;
                    }
                }

                if(!emptyClusterFound)
                {
                    next = 0;
                }
            }
            else
            {
                next = 0;
            }
        }

        return next;
    }

    private int readFATEntry(int cluster) throws FATException
    {
        int offset = 0;

        if(FATType == FS_TYPE_FAT16)
        {
            // Entries are 2 bytes wide.
            offset = cluster << 1;
        }
        else if(FATType == FS_TYPE_FAT32)
        {
            // Entries are 4 bytes wide.
            offset = cluster << 2;
        }
        else
        {
            throw new FATException("Unrecognized FAT Type");
        }

        // Start of the FAT table plus start address of the sector containing offset.
        int sectorAddress = tableAddresses[0] + ((offset >> shiftBytesPerSector) << shiftBytesPerSector);

        // Index into the table from the beginning of the sector.
        offset = offset & (bytesPerSector - 1);

        synchronized(sector2)
        {
            // Read the relevant sector of the FAT table
            if(!disk.read(sectorAddress, sector2, 0, bytesPerSector))
            {
                throw new FATException("Error reading disk");
            }

            if(FATType == FS_TYPE_FAT16)
            {
                return ArrayUtils.getShort(sector2, offset) & FAT16_MASK;
            }
            else if(FATType == FS_TYPE_FAT32)
            {
                return ArrayUtils.getInt(sector2, offset) & FAT32_MASK;
            }
            else
            {
                throw new FATException("Unrecognized FAT Type");
            }
        }
    }

    private void writeFATEntry(int cluster, int value) throws FATException
    {
        int offset = 0;

        if(FATType == FS_TYPE_FAT16)
        {
            // Entries are 2 bytes wide.
            offset = cluster << 1;
        }
        else if(FATType == FS_TYPE_FAT32)
        {
            // Entries are 4 bytes wide.
            offset = cluster << 2;
        }
        else
        {
            throw new FATException("Unrecognized FAT Type");
        }

        for(int i = 0; i < tableAddresses.length; i++)
        {
            // Start of the FAT table plus offset into the table.
            int sectorAddress = tableAddresses[i] + offset;

            synchronized(sector2)
            {
                if(FATType == FS_TYPE_FAT16)
                {
                    ArrayUtils.putShort(value & FAT16_MASK, sector2, 0);
                    if(!disk.write(sectorAddress, sector2, 0, 2))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -