public synchronized byte[] read(long pos, int length) throws IOException {
    if (pos >= this.fileLength) return null;

    this.offset = pos + length;

    DataOutputX out = new DataOutputX();
    int posOnBlock = (int) (pos % blockSize);
    if (posOnBlock > 0) {
      // long blockNum = (pos / blockSize);
      byte[] blockBytes = getReadBlock(pos / blockSize);
      if (blockBytes == null) {
        return null;
      }
      if (blockBytes.length < blockSize) {
        int readLen = Math.min(blockBytes.length - posOnBlock, length);
        return DataInputX.get(blockBytes, posOnBlock, readLen);
      }

      int readLen = Math.min(blockSize - posOnBlock, length);
      out.write(DataInputX.get(blockBytes, posOnBlock, readLen));

      length -= readLen;
      pos += readLen;
    }

    int blockCount = length / blockSize;

    for (int i = 0; i < blockCount; i++) {
      // long blockNum = (int) (pos / blockSize);
      byte[] blockBytes = getReadBlock(pos / blockSize);
      if (blockBytes == null) {
        return out.toByteArray();
      }
      out.write(blockBytes);

      pos += blockSize;
      length -= blockSize;
    }

    if (length == 0) {
      return out.toByteArray();
    }

    int remainder = length;

    //	long blockNum = (int) (pos / blockSize);
    byte[] block = getReadBlock(pos / blockSize);
    if (block != null) {
      remainder = Math.min(block.length, remainder);
      out.write(DataInputX.get(block, 0, remainder));
    }

    return out.toByteArray();
  }
 public short readShort(long pos) throws IOException {
   byte[] buf = read(pos, 2);
   return DataInputX.toShort(buf, 0);
 }
 public int readInt(long pos) throws IOException {
   byte[] buf = read(pos, 4);
   return DataInputX.toInt(buf, 0);
 }