Как стать автором
Обновить

Быстрый алгоритм подсчёта контрольной суммы для больших JAR файлов

Время на прочтение3 мин
Количество просмотров3.3K

Задача


Написать на pure-Java быстрый алгоритм для подсчета контрольной суммы JAR файла (>1G), по-возможности обойтись без сторонних библиотек.

Стандарный способ


Использовать MD5 дайджест для всего содержимого файла.

MessageDigest digest = MessageDigest.getInstance("MD5");<br/>
byte[]buf = new byte[1024];<br/>
int len = 0;<br/>
InputStream stream = new BufferedInputStream(new FileInputStream(new File("/path/to/jar/file")));<br/>
while((len = stream.read(buf)) > 0){<br/>
    digest.update(buf, 0, len);<br/>
}<br/>
stream.close();<br/>
byte[] md5sum = digest.digest();<br/>
 


Но, можно воспользоваться тем фактом что JAR уже содержит CRC для каждого из файла в архиве.
Используем MD5 дайджест только для CRC последовательности.

Финальная версия


import java.io.*;<br/>
import java.math.*;<br/>
import java.security.*;<br/>
import java.util.*;<br/>
import java.util.jar.*;<br/>
 <br/>
public class JarFileChecksum {<br/>
    private final File jarFile;<br/>
 <br/>
    public JarFileChecksum(File jarFile) {<br/>
        this.jarFile = jarFile;<br/>
    }<br/>
 <br/>
    public String getChecksum() throws Exception{<br/>
        MessageDigest digest = MessageDigest.getInstance("MD5");<br/>
        JarFile jar = new JarFile(jarFile);<br/>
        int crc;<br/>
        byte[]buf = new byte[4];<br/>
        for(Enumeration<JarEntry> e=jar.entries();e.hasMoreElements();){<br/>
            JarEntry entry = e.nextElement();<br/>
            // CRC на самом деле integer<br/>
            crc = (int)entry.getCrc();<br/>
            // split crc to bytes<br/>
            buf[0] = (byte)((crc>>24) & 0xFF);<br/>
            buf[1] = (byte)((crc>>16) & 0xFF);<br/>
            buf[2] = (byte)((crc>>8)  & 0xFF);<br/>
            buf[3] = (byte)(crc & 0xFF);<br/>
            digest.update(buf);<br/>
        }<br/>
        jar.close();<br/>
        byte[] md5sum = digest.digest();<br/>
        // превратим в String<br/>
        BigInteger bigInt = new BigInteger(1, md5sum);<br/>
        return bigInt.toString(16);<br/>
    }<br/>
}


Тесты


Для тестирования был выбран JAR файл размером 1.6G, 37000 файлов и 1500 директорий.

Первый способ:140 секунды
Второй способ: 0.5 секунды
Теги:
Хабы:
-1
Комментарии8

Публикации

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн