📄 blockfile.java
字号:
writeBlock(b, currentBlock);
}
/**
* Write to the specified logical position.
*
* @param b the bytes to be written.
* @param blockNo the logical index.
* @exception IOException if physical writing fails.
*/
public void writeBlock(byte[] b, int blockNo) throws IOException{
writePhysicalBlock(b, pointers[blockNo]);
}
/**
* Write to the specified physical postion.
*
* @param b the bytes to be written.
* @param blockNo the logical index.
* @exception IOException if physical writing fails.
*/
public void writePhysicalBlock(byte[] b, int blockNo) throws IOException{
/*if(fileCache != null){
fileCache.put(new Integer(blockNo), b);
return;
}*/
file.seek(blockNo * blockSize);
file.write(b);
writeOps++;
}
/**
* Read the next logical block from the current block index.
*
* @return an array of bytes.
* @exception IOException if physical reading fails.
*/
public byte[] readNextBlock() throws IOException{
if(currentBlock < numBlocks)
return readBlock(currentBlock + 1);
else
return null;
}
/**
* Read the previous logical block from the current block index.
*
* @return an array of bytes.
* @exception IOException if physical reading fails.
*/
public byte[] readPreviousBlock() throws IOException{
if(currentBlock == 0)
return null;
return readBlock(currentBlock - 1);
}
/**
* Insert a new block after the specified logical index. So if the
* specified index is 0 a the new block will have the logcial index
* of 1. To insert a block at the first logical position in the file
* use -1.
*
* @param blockNo the previous index of the current block.
* @exception IOException if physical writing fails.
*/
public void insertBlock(int blockNo) throws IOException{
try{
currentBlock = blockNo + 1;
highBlock += 1;
//System.out.println("new length: "+file.length()+" "+blockSize);
//file.setLength(file.length() + blockSize);
numBlocks++;
if((numBlocks) == pointers.length - 1){ //we have to grow the pointers
System.out.println("growing pointers");
short[] tmp = new short[pointers.length * 2];
System.arraycopy(pointers, 0, tmp, 0, pointers.length);
pointers = tmp;
}
if(currentBlock == numBlocks)
pointers[currentBlock] = highBlock;
else
System.arraycopy(pointers, currentBlock, pointers, currentBlock + 1, numBlocks - blockNo);
pointers[currentBlock] = highBlock;
}
catch(Exception e){
System.out.println(pointers.length+" "+currentBlock+" "+numBlocks+" "+blockNo);
throw new IOException(e.toString());
}
}
/**
* Remove the specified block from the file. It is only the logical reference that
* will be unlinked, i.e. the method does not fill the block with zeros or something.
* Also note that the physical space will be unavailable to new blocks until a
* defragment has been issued.
*
* @param blockNo the logical block to delete
* @see BlockFile#defragment()
*/
public void removeBlock(int blockNo){
/*if(fileCache != null)
fileCache.remove(new Integer(pointers[blockNo]));
*/
if(numBlocks-1 == 0){
System.out.println("Removing all data");
try{
file.setLength(0);
}
catch(IOException e){System.out.println(e);}
pointers = new short[256];
currentBlock = -1;
numBlocks = 0;
highBlock = -1;
return;
}
System.arraycopy(pointers, blockNo + 1, pointers, blockNo, numBlocks - blockNo + 1);
numBlocks--;
}
/**
* Prints header information of the block file and the logical and physical mapping.
*/
public String toString(){
StringBuffer sbuff = new StringBuffer();
sbuff.append("File name: "+fileName+'\n');
sbuff.append("Block size: "+blockSize+'\n');
sbuff.append("Num blocks: "+numBlocks+'\n');
sbuff.append("Highest logical block: "+highBlock+'\n');
sbuff.append("block capacity: "+pointers.length+'\n');
sbuff.append("Logical and physical block order: ");
for(int i = 0; i < numBlocks; i++){
sbuff.append(i+":"+pointers[i]+" ");
}
sbuff.append('\n');
return sbuff.toString();
}
/**
* The defragment removes unused space and remapps the logical/physical
* mapping so that the logical block 0 will be the first block in the file,
* and so on.
*
* @exception IOException if physical read/write fails.
*/
public void defragment() throws IOException{
//writeHeader();
/*if(fileCache != null)
fileCache.emptyCache();
*/
RandomAccessFile raf = new RandomAccessFile("defragment.tmp", "rw");
RandomAccessFile raf1 = new RandomAccessFile("defragment_pointers.tmp", "rw");
synchronized(file){
int i;
for(i = 0; i < numBlocks; i++){
raf.write(readBlock(i));
}
raf.close();
//now write the header:
//byte hBlock[] = new byte[18 + (numBlocks * 2)];
//ByteStorage.writeInt(hBlock, 0, numBlocks);
//ByteStorage.writeInt(hBlock, 4, currentBlock);
//ByteStorage.writeInt(hBlock, 8, pointers.length);
//ByteStorage.writeInt(hBlock, 12, blockSize);
//ByteStorage.writeShort(hBlock, 16, (short) (numBlocks - 1));
//Write header:
ByteBuffer bb = ByteBuffer.allocate(18 + (numBlocks * 2));
bb.putInt(numBlocks);
bb.putInt(currentBlock);
bb.putInt(pointers.length);
bb.putInt(blockSize);
bb.putShort((short) (numBlocks -1));
for(i = 0; i < numBlocks; i++){
bb.putShort((short) i);
}
bb.flip();
raf1.getChannel().write(bb);
raf1.close();
file.close();
File f = new File(fileName+BLOCK_FILE_EXTENSION);
f.delete();
File f1 = new File("defragment.tmp");
f1.renameTo(f);
f = new File(fileName+POINTER_FILE_EXTENSION);
f.delete();
f1 = new File("defragment_pointers.tmp");
f1.renameTo(f);
openFile();
}
}
/**
* Tries to close the file if it is open
*
*/
protected void finalize(){
try{
closeFile();
}
catch(IOException e){System.out.println(e);}
}
/********************PRIVATE SECTION*****************************************/
private void writeHeader() throws IOException{
RandomAccessFile raf = new RandomAccessFile(fileName + POINTER_FILE_EXTENSION, "rw");
ByteBuffer bb = ByteBuffer.allocate(18 + (numBlocks * 2));
bb.putInt(numBlocks);
bb.putInt(currentBlock);
bb.putInt(pointers.length);
bb.putInt(blockSize);
bb.putShort(highBlock);
for(int i = 0; i < numBlocks; i++){
bb.putShort((short) pointers[i]);
}
bb.flip();
raf.getChannel().write(bb);
raf.close();
}
private void createFile() throws IOException{
file = new RandomAccessFile(fileName+BLOCK_FILE_EXTENSION, "rw");
file.setLength(0);
currentBlock = -1;
numBlocks = 0;
highBlock = -1;
}
private void openFile() throws IOException{
//read the pointers:
RandomAccessFile raf = new RandomAccessFile(fileName + POINTER_FILE_EXTENSION, "r");
ByteBuffer bb = ByteBuffer.allocate((int) raf.length());
raf.getChannel().read(bb);
bb.flip();
numBlocks = bb.getInt();
currentBlock = bb.getInt();
pointers = new short[bb.getInt()];
blockSize = bb.getInt();
highBlock = bb.getShort();
for(int i = 0; i < numBlocks; i++)
pointers[i] = bb.getShort();
raf.close();
//open block file:
file = new RandomAccessFile(fileName+BLOCK_FILE_EXTENSION, "rw");
}
/*********************************INNER CLASSES**************************/
class BFIterator implements Iterator{
int count = numBlocks;
int cursor = 0;
int lastRet = -1;
public BFIterator(int blockNo, boolean logical){
cursor = (logical)?blockNo:getLogicalBlockNo(blockNo);
if(cursor < 0) //the physical blockNo did not exsist
cursor = numBlocks+10;
}
public BFIterator(){
;
}
public boolean hasNext(){
return (cursor < numBlocks);
}
public Object next(){
try{
check();
if(cursor >= numBlocks)
throw new NoSuchElementException();
Object block = readBlock(cursor);
lastRet = cursor++;
return block;
}
catch(IOException e){
throw new NoSuchElementException();
}
}
public void remove(){
if(lastRet == -1)
throw new IllegalStateException();
check();
removeBlock(lastRet);
if(lastRet < cursor)
cursor--;
lastRet = -1;
count = numBlocks;
}
private void check(){
if(count != numBlocks)
throw new ConcurrentModificationException();
}
}
/*
class Callback implements CacheCallback{
public void remove(Object key, Object value){
try{
file.seek(((Integer)key).intValue() * blockSize);
file.write((byte[])value);
writeOps++;
}
catch(IOException e){
System.out.println(e);
}
}
}
*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -