fatfile.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 211 行

JAVA
211
字号
/**
 * $Id: FatFile.java,v 1.2 2003/11/29 03:33:28 gbin Exp $
 */
package org.jnode.fs.fat;

import java.io.IOException;

import org.jnode.driver.block.BlockDeviceAPI;
import org.jnode.fs.FSFile;

/**
 * A File instance is the in-memory representation of a single file (chain of
 * clusters).
 * 
 * @author epr
 */
public class FatFile extends FatObject implements FSFile {
	
	private long startCluster;
	private long length;
	private FatDirectory dir;
	private int clusterSize;
	private boolean isDir;
	private final FatDirEntry myEntry;

	public FatFile(FatFileSystem fs, FatDirEntry myEntry, long startCluster, long length, boolean isDir) {
		super(fs);
		this.myEntry = myEntry;
		this.startCluster = startCluster;
		this.length = length;
		this.clusterSize = fs.getClusterSize();
		this.isDir = isDir;
	}
	
	public synchronized void read(long fileOffset, byte[] dest, int destOfs, int len) throws IOException {
		
		final long max = (isDir) ? getLengthOnDisk() : getLength();
		if (fileOffset + len > max) {
			throw new IOException("Cannot read beyond the EOF");
		}

		final FatFileSystem fs = getFatFileSystem();
		final long[] chain = fs.getFat().getChain(startCluster);
		final BlockDeviceAPI api = fs.getBlockDeviceAPI();
		
		int chainIdx = (int)(fileOffset / clusterSize);
		if (fileOffset % clusterSize != 0) {
			int clusOfs = (int)(fileOffset % clusterSize);
			int size = Math.min(len, (int)(clusterSize - (fileOffset % clusterSize) - 1));
			api.read(getDevOffset(chain[chainIdx], clusOfs), dest, destOfs, size);
			fileOffset += size;
			len -= size;
			destOfs += size;
			chainIdx++; 
		}
		while (len > 0) {
			int size = Math.min(clusterSize, len);
			api.read(getDevOffset(chain[chainIdx], 0), dest, destOfs, size);
			len -= size;
			destOfs += size;
			chainIdx++;
		}	
	}

	public synchronized void write(long fileOffset, byte[] src, int srcOfs, int len) throws IOException {

		final long max = (isDir) ? getLengthOnDisk() : getLength();
		if (fileOffset > max) {
			throw new IOException("Cannot write beyond the EOF");
		}
        
      if (fileOffset + len > max) { // this is too short increase the size of the file
          setLength(fileOffset + len);
      }
		
		final FatFileSystem fs = getFatFileSystem();
		final long[] chain = fs.getFat().getChain(getStartCluster());
		final BlockDeviceAPI api = fs.getBlockDeviceAPI();

		int chainIdx = (int)(fileOffset / clusterSize);
		if (fileOffset % clusterSize != 0) {
			int clusOfs = (int)(fileOffset % clusterSize);
			int size = Math.min(len, (int)(clusterSize - (fileOffset % clusterSize) - 1));
			api.write(getDevOffset(chain[chainIdx], clusOfs), src, srcOfs, size);
			fileOffset += size;
			len -= size;
			srcOfs += size;
			chainIdx++; 
		}
		while (len > 0) {
			int size = Math.min(clusterSize, len);
			api.write(getDevOffset(chain[chainIdx], 0), src, srcOfs, size);
			len -= size;
			srcOfs += size;
			chainIdx++;
		}	
	}
	
	/**
	 * Sets the length.
	 * @param length The length to set
	 */
	public synchronized void setLength(long length) 
	throws IOException {
		
		if (this.length == length) {
			// Do nothing
			return;
		}
		
		final FatFileSystem fs = getFatFileSystem();
		final Fat fat = fs.getFat();
		final int nrClusters = (int)((length + clusterSize-1) / clusterSize);

       if (this.length == 0) {
			final long[] chain = fat.allocNew(nrClusters);
			this.startCluster = chain[0];
			this.myEntry.setStartCluster((int)startCluster);
		} else {
			final long[] chain = fs.getFat().getChain(startCluster);
		
			if (nrClusters != chain.length) {
				if (nrClusters > chain.length) {
					// Grow
					int count = nrClusters - chain.length; 
					while (count > 0) {
						fat.allocAppend(getStartCluster());
						count--;
					}								
				} else {
					// Shrink
					fat.setEof(chain[nrClusters-1]);
					for (int i = nrClusters; i < chain.length; i++) {
						fat.setFree(chain[i]);
					}
				}
			}
		}		
		
		this.length = length;
		this.myEntry.updateLength(length);
	}
	
	/**
	 * Returns the length.
	 * @return long
	 */
	public long getLength() {
		return length;
	}
	
	/**
	 * Gets the size this file occupies on disk
	 * @return long
	 */
	public long getLengthOnDisk() {
		if (this.length == 0) {
			return 0;
		} else {
			final FatFileSystem fs = getFatFileSystem();
			final long[] chain = fs.getFat().getChain(getStartCluster());
			return ((long)chain.length) * fs.getClusterSize();		
		}
	}

	/**
	 * Returns the startCluster.
	 * @return long
	 */
	public long getStartCluster() {
		return startCluster;
	}
	
	/**
	 * Gets the directory contained in this file.
	 * @return Directory
	 */
	public synchronized FatDirectory getDirectory()
	throws IOException {
		if (dir == null) {
			final FatFileSystem fs = getFatFileSystem();
			dir = new FatLfnDirectory(fs, this);
		}
		return dir;
	}
	
	/**
	 * Calculates the device offset (0-based) for the given cluster and offset
	 * within the cluster.
	 * @param cluster
	 * @param clusterOffset
	 * @return long
	 */
	protected long getDevOffset(long cluster, int clusterOffset) {
		final FatFileSystem fs = getFatFileSystem();
		final long filesOffset = FatUtils.getFilesOffset(fs.getBootSector());
		return filesOffset + clusterOffset + ((cluster - FatUtils.FIRST_CLUSTER) * clusterSize);
	}
	
	/**
	 * Flush any changes in this file to persistent storage
	 * @throws IOException
	 */
	protected void flush()
	throws IOException {
		if (dir != null) {
			dir.flush();
		}
	}
}

⌨️ 快捷键说明

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