1 23 package org.archive.util.ms; 24 25 import java.io.IOException ; 26 27 import org.archive.io.SeekInputStream; 28 import static org.archive.util.ms.BlockFileSystem.BLOCK_SIZE; 29 30 31 34 public class BlockInputStream extends SeekInputStream { 35 36 37 40 private int start; 41 42 43 46 private int block; 47 48 49 52 private BlockFileSystem bfs; 53 54 55 58 private SeekInputStream raw; 59 60 61 64 private long position; 65 66 67 70 private long expectedRawPosition; 71 72 73 76 private int blockBytesRead; 77 78 79 85 public BlockInputStream(BlockFileSystem bfs, int block) throws IOException { 86 this.raw = bfs.getRawInput(); 87 this.bfs = bfs; 88 this.start = block; 89 this.block = block; 90 this.position = 0; 91 seek(block, 0); 92 } 93 94 95 96 private void seek(long block, long rem) throws IOException { 97 assert rem < BLOCK_SIZE; 98 long pos = (block + 1) * BLOCK_SIZE + rem; 99 blockBytesRead = (int)rem; 100 expectedRawPosition = pos; 101 raw.position(pos); 102 } 103 104 105 private void ensureRawPosition() throws IOException { 106 if (raw.position() != expectedRawPosition) { 107 raw.position(expectedRawPosition); 108 } 109 } 110 111 private boolean ensureBuffer() throws IOException { 112 if (block < 0) { 113 return false; 114 } 115 ensureRawPosition(); 116 if (blockBytesRead < BLOCK_SIZE) { 117 return true; 118 } 119 block = bfs.getNextBlock(block); 120 if (block < 0) { 121 return false; 122 } 123 seek(block, 0); 124 return true; 125 } 126 127 128 public long skip(long v) throws IOException { 129 int r = read(); 131 return (r < 0) ? 0 : 1; 132 } 133 134 public int read() throws IOException { 135 if (!ensureBuffer()) { 136 return -1; 137 } 138 int r = raw.read(); 139 position++; 140 expectedRawPosition++; 141 blockBytesRead++; 142 return r; 143 } 144 145 146 public int read(byte[] b, int ofs, int len) throws IOException { 147 if (!ensureBuffer()) { 148 return 0; 149 } 150 int rem = BLOCK_SIZE - (int)(position % BLOCK_SIZE); 151 len = Math.min(len, rem); 152 int c = raw.read(b, ofs, len); 153 position += c; 154 expectedRawPosition += c; 155 blockBytesRead++; 156 return len; 157 } 158 159 160 public int read(byte[] b) throws IOException { 161 return read(b, 0, b.length); 162 } 163 164 165 public long position() { 166 return position; 167 } 168 169 170 public void position(long v) throws IOException { 171 ensureRawPosition(); 172 if (v == position) { 173 return; 174 } 175 176 if (v / BLOCK_SIZE == position / BLOCK_SIZE) { 178 long rem = v % BLOCK_SIZE; 179 seek(block, rem); 180 position = v; 181 return; 182 } 183 184 if (v > position) { 185 seekAfter(v); 186 } else { 187 seekBefore(v); 188 } 189 } 190 191 192 private void seekAfter(long v) throws IOException { 193 long currentBlock = position / BLOCK_SIZE; 194 long destBlock = v / BLOCK_SIZE; 195 long blockAdvance = destBlock - currentBlock; 196 for (int i = 0; i < blockAdvance; i++) { 197 block = bfs.getNextBlock(block); 198 } 199 seek(block, v % BLOCK_SIZE); 200 position = v; 201 } 202 203 204 private void seekBefore(long v) throws IOException { 205 long blockAdvance = (v - 1) / BLOCK_SIZE; 206 block = start; 207 for (int i = 0; i < blockAdvance; i++) { 208 block = bfs.getNextBlock(block); 209 } 210 seek(block, v % BLOCK_SIZE); 211 } 212 } 213 | Popular Tags |