[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]java版本的CRC64代码,ECMA-182标准

上一篇:[备忘]HttpURLConnection通过HEAD请求获取信息,获取OSS文件的CRC64值
下一篇:[备忘]gdb做jvm的dump

添加日期:2021/11/18 15:51:23 快速返回   返回列表 阅读803次
https://github.com/MrBuddyCasino/crc-64/blob/master/crc-64/src/main/java/net/boeckling/crc/CRC64.java


package xxx.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.Checksum;

/**
 * CRC-64 implementation with ability to combine checksums calculated over
 * different blocks of data.
 *
 * This is a faster version of the original implementation by R. Nikitchenko,
 * incorporating the nested lookup table design by Mark Adler (see <a
 * href="http://stackoverflow.com/a/20579405/58962">Stackoverflow</a>).
 *
 * Throughput rose from 375 MB/s to 1150 MB/s on a 2,3 GHz i7, which is 3.06
 * times faster.
 *
 * @author Roman Nikitchenko (roman@nikitchenko.dp.ua)
 * @author Michael Böckling
 */
public class CRC64 implements Checksum
{

    private final static long POLY = (long) 0xc96c5795d7870f42L; // ECMA-182

    /* CRC64 calculation table. */
    private final static long[][] table;

    /* Current CRC value. */
    private long value;

    static
    {
        /*
         * Nested tables as described by Mark Adler:
         * http://stackoverflow.com/a/20579405/58962
         */
        table = new long[8][256];

        for (int n = 0; n < 256; n++)
        {
            long crc = n;
            for (int k = 0; k < 8; k++)
            {
                if ((crc & 1) == 1)
                {
                    crc = (crc >>> 1) ^ POLY;
                }
                else
                {
                    crc = (crc >>> 1);
                }
            }
            table[0][n] = crc;
        }

        /* generate nested CRC table for future slice-by-8 lookup */
        for (int n = 0; n < 256; n++)
        {
            long crc = table[0][n];
            for (int k = 1; k < 8; k++)
            {
                crc = table[0][(int) (crc & 0xff)] ^ (crc >>> 8);
                table[k][n] = crc;
            }
        }
    }

    /**
     * Initialize with a value of zero.
     */
    public CRC64()
    {
        this.value = 0;
    }

    /**
     * Initialize with a custom CRC value.
     *
     * @param value
     */
    public CRC64(long value)
    {
        this.value = value;
    }

    /**
     * Initialize by calculating the CRC of the given byte blocks.
     *
     * @param b
     *            block of bytes
     * @param len
     *            number of bytes to process
     */
    public CRC64(byte[] b, int len)
    {
        this.value = 0;
        update(b, len);
    }

    /**
     * Initialize by calculating the CRC of the given byte blocks.
     *
     * @param b
     *            block of bytes
     * @param off
     *            starting offset of the byte block
     * @param len
     *            number of bytes to process
     */
    public CRC64(byte[] b, int off, int len)
    {
        this.value = 0;
        update(b, off, len);
    }

    /**
     * Construct new CRC64 instance from byte array.
     */
    public static CRC64 fromBytes(byte[] b)
    {
        long l = 0;
        for (int i = 0; i < 4; i++)
        {
            l <<= 8;
            l ^= (long) b[i] & 0xFF;
        }
        return new CRC64(l);
    }

    /**
     * Calculate the CRC64 of the given file's content.
     *
     * @param f
     * @return new {@link CRC64} instance initialized to the file's CRC value
     * @throws IOException
     *             in case the {@link FileInputStream#read(byte[])} method fails
     */
    public static CRC64 fromFile(File f) throws IOException
    {
        return fromInputStream(new FileInputStream(f));
    }

    /**
     * Calculate the CRC64 of the given {@link InputStream} until the end of the
     * stream has been reached.
     *
     * @param in
     *            the stream will be closed automatically
     * @return new {@link CRC64} instance initialized to the {@link InputStream}'s CRC value
     * @throws IOException
     *             in case the {@link InputStream#read(byte[])} method fails
     */
    public static CRC64 fromInputStream(InputStream in) throws IOException
    {
        try
        {
            CRC64 crc = new CRC64();
            byte[] b = new byte[65536];
            int l = 0;

            while ((l = in.read(b)) != -1)
            {
                crc.update(b, l);
            }

            return crc;

        } finally
        {
            in.close();
        }
    }

    /**
     * Get 8 byte representation of current CRC64 value.
     */
    public byte[] getBytes()
    {
        byte[] b = new byte[8];
        for (int i = 0; i < 8; i++)
        {
            b[7 - i] = (byte) (this.value >>> (i * 8));
        }
        return b;
    }

    /**
     * Get long representation of current CRC64 value.
     */
    public long getValue()
    {
        return this.value;
    }

    /**
     * Update CRC64 with new byte block.
     */
    public void update(byte[] b, int len) {
        this.update(b, 0, len);
    }

    /**
     * Update CRC64 with new byte block.
     */
    public void update(byte[] b, int off, int len)
    {
        this.value = ~this.value;

        /* fast middle processing, 8 bytes (aligned!) per loop */

        int idx = off;
        while (len >= 8)
        {
            value = table[7][(int) (value & 0xff ^ (b[idx] & 0xff))]
                    ^ table[6][(int) ((value >>> 8) & 0xff ^ (b[idx + 1] & 0xff))]
                    ^ table[5][(int) ((value >>> 16) & 0xff ^ (b[idx + 2] & 0xff))]
                    ^ table[4][(int) ((value >>> 24) & 0xff ^ (b[idx + 3] & 0xff))]
                    ^ table[3][(int) ((value >>> 32) & 0xff ^ (b[idx + 4] & 0xff))]
                    ^ table[2][(int) ((value >>> 40) & 0xff ^ (b[idx + 5] & 0xff))]
                    ^ table[1][(int) ((value >>> 48) & 0xff ^ (b[idx + 6] & 0xff))]
                    ^ table[0][(int) ((value >>> 56) ^ b[idx + 7] & 0xff)];
            idx += 8;
            len -= 8;
        }

        /* process remaining bytes (can't be larger than 8) */
        while (len > 0)
        {
            value = table[0][(int) ((this.value ^ b[idx]) & 0xff)] ^ (this.value >>> 8);
            idx++;
            len--;
        }

        this.value = ~this.value;
    }

    public void update(int b) {
        this.update(new byte[]{(byte)b}, 0, 1);
    }

    public void reset() {
        this.value = 0;
    }

    // dimension of GF(2) vectors (length of CRC)
    private static final int GF2_DIM = 64;

    private static long gf2MatrixTimes(long[] mat, long vec)
    {
        long sum = 0;
        int idx = 0;
        while (vec != 0)
        {
            if ((vec & 1) == 1)
                sum ^= mat[idx];
            vec >>>= 1;
            idx++;
        }
        return sum;
    }

    private static void gf2MatrixSquare(long[] square, long[] mat)
    {
        for (int n = 0; n < GF2_DIM; n++)
            square[n] = gf2MatrixTimes(mat, mat[n]);
    }

    /*
     * Return the CRC-64 of two sequential blocks, where summ1 is the CRC-64 of
     * the first block, summ2 is the CRC-64 of the second block, and len2 is the
     * length of the second block.
     */
    static public CRC64 combine(CRC64 summ1, CRC64 summ2, long len2)
    {
        // degenerate case.
        if (len2 == 0)
            return new CRC64(summ1.getValue());

        int n;
        long row;
        long[] even = new long[GF2_DIM]; // even-power-of-two zeros operator
        long[] odd = new long[GF2_DIM]; // odd-power-of-two zeros operator

        // put operator for one zero bit in odd
        odd[0] = POLY; // CRC-64 polynomial

        row = 1;
        for (n = 1; n < GF2_DIM; n++)
        {
            odd[n] = row;
            row <<= 1;
        }

        // put operator for two zero bits in even
        gf2MatrixSquare(even, odd);

        // put operator for four zero bits in odd
        gf2MatrixSquare(odd, even);

        // apply len2 zeros to crc1 (first square will put the operator for one
        // zero byte, eight zero bits, in even)
        long crc1 = summ1.getValue();
        long crc2 = summ2.getValue();
        do
        {
            // apply zeros operator for this bit of len2
            gf2MatrixSquare(even, odd);
            if ((len2 & 1) == 1)
                crc1 = gf2MatrixTimes(even, crc1);
            len2 >>>= 1;

            // if no more bits set, then done
            if (len2 == 0)
                break;

            // another iteration of the loop with odd and even swapped
            gf2MatrixSquare(odd, even);
            if ((len2 & 1) == 1)
                crc1 = gf2MatrixTimes(odd, crc1);
            len2 >>>= 1;

            // if no more bits set, then done
        } while (len2 != 0);

        // return combined crc.
        crc1 ^= crc2;
        return new CRC64(crc1);
    }

}



用法举例:


long fileCRC64 = 0;
try {
    fileCRC64 = xxx.util.CRC64.fromFile(new File("D:\\xxx.jpg")).getValue();
} catch (IOException e) {
    e.printStackTrace();
}
System.out.println(fileCRC64);

 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved