/* * gets an (uncompressed) stream representing the chunk data returns null if * the chunk is not found or an error occurs */ public synchronized DataInputStream getChunkDataInputStream(int x, int z) { if (outOfBounds(x, z)) { debugln("READ", x, z, "out of bounds"); return null; } try { int offset = getOffset(x, z); if (offset == 0) { // debugln("READ", x, z, "miss"); return null; } int sectorNumber = offset >> 8; int numSectors = offset & 0xFF; if (sectorNumber + numSectors > sectorFree.size()) { debugln("READ", x, z, "invalid sector"); return null; } file.seek(sectorNumber * SECTOR_BYTES); int length = file.readInt(); if (length > SECTOR_BYTES * numSectors) { debugln("READ", x, z, "invalid length: " + length + " > 4096 * " + numSectors); return null; } byte version = file.readByte(); if (version == VERSION_GZIP) { byte[] data = new byte[length - 1]; file.read(data); DataInputStream ret = new DataInputStream( new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(data)))); // debug("READ", x, z, " = found"); return ret; } else if (version == VERSION_DEFLATE) { byte[] data = new byte[length - 1]; file.read(data); DataInputStream ret = new DataInputStream( new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(data)))); // debug("READ", x, z, " = found"); return ret; } debugln("READ", x, z, "unknown version " + version); return null; } catch (IOException e) { debugln("READ", x, z, "exception"); return null; } }
/** * Read block from file. * * @param file - File to read. * @param off - Marker position in file to start read from if {@code -1} read last blockSz bytes. * @param blockSz - Maximum number of chars to read. * @param lastModified - File last modification time. * @return Read file block. * @throws IOException In case of error. */ public static VisorFileBlock readBlock(File file, long off, int blockSz, long lastModified) throws IOException { RandomAccessFile raf = null; try { long fSz = file.length(); long fLastModified = file.lastModified(); long pos = off >= 0 ? off : Math.max(fSz - blockSz, 0); // Try read more that file length. if (fLastModified == lastModified && fSz != 0 && pos >= fSz) throw new IOException( "Trying to read file block with wrong offset: " + pos + " while file size: " + fSz); if (fSz == 0) return new VisorFileBlock(file.getPath(), pos, fLastModified, 0, false, EMPTY_FILE_BUF); else { int toRead = Math.min(blockSz, (int) (fSz - pos)); byte[] buf = new byte[toRead]; raf = new RandomAccessFile(file, "r"); raf.seek(pos); int cntRead = raf.read(buf, 0, toRead); if (cntRead != toRead) throw new IOException( "Count of requested and actually read bytes does not match [cntRead=" + cntRead + ", toRead=" + toRead + ']'); boolean zipped = buf.length > 512; return new VisorFileBlock( file.getPath(), pos, fSz, fLastModified, zipped, zipped ? zipBytes(buf) : buf); } } finally { U.close(raf, null); } }