Changes between Version 69 and Version 70 of HashSourceCodes


Ignore:
Timestamp:
Nov 13, 2020, 5:59:31 AM (4 years ago)
Author:
os
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • HashSourceCodes

    v69 v70  
    22422242}
    22432243}}}
     2244
     2245== Kotlin ==
     2246Kotlin implementation by taohid32[at]gmail com
     2247{{{
     2248import java.io.*
     2249import java.nio.ByteBuffer
     2250import java.nio.ByteOrder
     2251import java.nio.channels.FileChannel
     2252import kotlin.math.max
     2253import kotlin.math.min
     2254
     2255class MovieHashUtil {
     2256
     2257    companion object {
     2258        private const val HASH_CHUNK_SIZE = 64 * 1024
     2259    }
     2260
     2261    @Throws(IOException::class)
     2262    fun computeHash(file: File): String {
     2263        val size = file.length()
     2264        val chunkSizeForFile = min(HASH_CHUNK_SIZE.toLong(), size)
     2265        FileInputStream(file).channel.use { fileChannel ->
     2266            val head = computeChunkHash(
     2267                fileChannel.map(
     2268                    FileChannel.MapMode.READ_ONLY,
     2269                    0,
     2270                    chunkSizeForFile
     2271                )
     2272            )
     2273            val tail = computeChunkHash(
     2274                fileChannel.map(
     2275                    FileChannel.MapMode.READ_ONLY,
     2276                    max(size - HASH_CHUNK_SIZE, 0),
     2277                    chunkSizeForFile
     2278                )
     2279            )
     2280            return String.format("%016x", size + head + tail)
     2281        }
     2282    }
     2283
     2284    @Throws(IOException::class)
     2285    fun computeHash(stream: InputStream?, length: Long): String {
     2286        val chunkSizeForFile = min(HASH_CHUNK_SIZE.toLong(), length)
     2287            .toInt()
     2288
     2289        // buffer that will contain the head and the tail chunk, chunks will overlap if length is smaller than two chunks
     2290        val chunkBytes = ByteArray(
     2291            min(2 * HASH_CHUNK_SIZE.toLong(), length).toInt()
     2292        )
     2293        val inputStream = DataInputStream(stream)
     2294
     2295        // first chunk
     2296        inputStream.readFully(chunkBytes, 0, chunkSizeForFile)
     2297        var position = chunkSizeForFile.toLong()
     2298        val tailChunkPosition = length - chunkSizeForFile
     2299
     2300        // seek to position of the tail chunk, or not at all if length is smaller than two chunks
     2301        while (position < tailChunkPosition && inputStream.skip(tailChunkPosition - position)
     2302                .let { position += it; position } >= 0
     2303        );
     2304
     2305        // second chunk, or the rest of the data if length is smaller than two chunks
     2306        inputStream.readFully(chunkBytes, chunkSizeForFile, chunkBytes.size - chunkSizeForFile)
     2307        val head = computeChunkHash(ByteBuffer.wrap(chunkBytes, 0, chunkSizeForFile))
     2308        val tail = computeChunkHash(
     2309            ByteBuffer.wrap(
     2310                chunkBytes,
     2311                chunkBytes.size - chunkSizeForFile,
     2312                chunkSizeForFile
     2313            )
     2314        )
     2315        return String.format("%016x", length + head + tail)
     2316    }
     2317
     2318    private fun computeChunkHash(buffer: ByteBuffer): Long {
     2319        val longBuffer = buffer.order(ByteOrder.LITTLE_ENDIAN).asLongBuffer()
     2320        var hash: Long = 0
     2321        while (longBuffer.hasRemaining()) {
     2322            hash += longBuffer.get()
     2323        }
     2324        return hash
     2325    }
     2326
     2327}
     2328}}}