| 145 | } |
| 146 | |
| 147 | |
| 148 | public static String computeHash(InputStream stream, long length) throws IOException { |
| 149 | |
| 150 | int chunkSizeForFile = (int) Math.min(HASH_CHUNK_SIZE, length); |
| 151 | |
| 152 | // buffer that will contain the head and the tail chunk, chunks will overlap if length is smaller than two chunks |
| 153 | byte[] chunkBytes = new byte[(int) Math.min(2 * HASH_CHUNK_SIZE, length)]; |
| 154 | |
| 155 | DataInputStream in = new DataInputStream(stream); |
| 156 | |
| 157 | // first chunk |
| 158 | in.readFully(chunkBytes, 0, chunkSizeForFile); |
| 159 | |
| 160 | long position = chunkSizeForFile; |
| 161 | long tailChunkPosition = length - chunkSizeForFile; |
| 162 | |
| 163 | // seek to position of the tail chunk, or not at all if length is smaller than two chunks |
| 164 | while (position < tailChunkPosition && (position += in.skip(tailChunkPosition - position)) >= 0); |
| 165 | |
| 166 | // second chunk, or the rest of the data if length is smaller than two chunks |
| 167 | in.readFully(chunkBytes, chunkSizeForFile, chunkBytes.length - chunkSizeForFile); |
| 168 | |
| 169 | long head = computeHashForChunk(ByteBuffer.wrap(chunkBytes, 0, chunkSizeForFile)); |
| 170 | long tail = computeHashForChunk(ByteBuffer.wrap(chunkBytes, chunkBytes.length - chunkSizeForFile, chunkSizeForFile)); |
| 171 | |
| 172 | return String.format("%016x", length + head + tail); |