package hdgl.db.store.impl.hdfs.mapreduce; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; public class JumpInputStream extends InputStream { private static final int BUFFERSIZE = 64; byte[] buffer = new byte[BUFFERSIZE]; int buflen = 0; int bufreaded = 0; boolean jumped = false; FSDataInputStream in1; FSDataInputStream in2; int jumplen; FileStatus[] jumpfiles; FileSystem fs; public JumpInputStream(FileStatus[] in1, FileStatus[] in2, long seekpos, int jumplen, FileSystem fs) throws IOException { int currentFile = 0; FileStatus f = in1[currentFile++]; while(f.getLen() <= seekpos){ if(currentFile >= jumpfiles.length){ throw new EOFException("end of the pseudo file"); } seekpos -= f.getLen(); f = in1[currentFile++]; } this.in1 = fs.open(f.getPath()); this.in1.seek(seekpos); this.jumplen = jumplen - 8; this.jumpfiles = in2; this.fs= fs; } boolean loadbuffer() throws IOException{ if(bufreaded == BUFFERSIZE){ buflen = 0; bufreaded = 0; } if(!jumped){ if(jumplen==0){ long offset = in1.readLong(); int currentFile = 0; FileStatus f = jumpfiles[currentFile++]; while(f.getLen() <= offset){ if(currentFile>=jumpfiles.length){ throw new EOFException("end of the pseudo file"); } offset -= f.getLen(); f = jumpfiles[currentFile++]; } in2 = fs.open(f.getPath()); in2.seek(offset); int len = BUFFERSIZE - buflen; int readed = in2.read(buffer, buflen, len); if(readed==0) return false; buflen += readed; }else{ int len = BUFFERSIZE - buflen; int readed = in1.read(buffer, buflen, jumplen>len?jumplen:len); if(readed==0) return false; jumplen -= readed; buflen += readed; } }else{ int len = BUFFERSIZE - buflen; int readed = in2.read(buffer, buflen, len); if(readed==0) return false; buflen += readed; } return true; } @Override public int read() throws IOException { if(buflen <= bufreaded){ loadbuffer(); } return buffer[bufreaded++]; } @Override public int read(byte[] b) throws IOException { return read(b, 0, b.length); } @Override public int read(byte[] b, int offset, int length) throws IOException { int count=0; while(length>0){ if(buflen <= bufreaded){ loadbuffer(); } int len = buflen - bufreaded; len = len>length?length:len; System.arraycopy(buffer, bufreaded, b, offset, len); length -=len; offset+=len; count+=len; } return count; } @Override public void close() throws IOException { try{ in1.close(); }finally{ if(in2!=null){ in2.close(); } } } }