数据文件不同读入方式的【CRC32】【循环冗余校验】计算效率比较

CRC(Cyclic Redundancy Check)循环冗余校验,在数据存储和数据通讯领域,为了保证数据的正确,就不得不采用校验检错的手段。在诸多检错手段中,CRC是最著名的一种。CRC的全称是循环冗余校验。

CRC的本质:是模-2除法的余数,采用的除数不同,CRC的类型也就不一样。通常,CRC的除数用生成多项式来表示。最常用的CRC码CRC-32的生成多项式如下所示:
在这里插入图片描述

由于CRC在通讯和数据处理软件中经常采用。对于一个数据文件,其CRC32的循环冗余校验码,有点类似于人类的指纹,不同的文件通常有不同的循环冗余校验码,相同的几率很小。

在Java语言的库中包含有CRC32循环冗余校验码计算的实用程序库。
下面我们对数据文件不同读入方式的【CRC32】【循环冗余校验】计算效率进行比较:

  • 用InputStream方式读文件,计算文件的CRC32校验和
	/***以InputStream方式读文件,计算文件的CRC32校验和***/
	public static long checknumInputStream(Path filename) throws IOException
	{
		try(InputStream stream = Files.newInputStream(filename)) 
		{
			CRC32 crc = new CRC32();
			int c;
			while ( (c = stream.read()) != -1) crc.update(c);
			
			return crc.getValue();
		}
	}
  • 用BufferedInputStream方式读文件,计算文件的CRC32校验和
		/***以BufferedInputStream方式读文件,计算文件的CRC32校验和***/
		public static long checknumBufferedInputStream(Path filename) throws IOException
		{
			try(InputStream stream = new BufferedInputStream(Files.newInputStream(filename))) 
			{
				CRC32 crc = new CRC32();
				int c;
				while ( (c = stream.read()) != -1) crc.update(c);
				
				return crc.getValue();
			}
		}
  • 用RandomAccessFile【随机存取】方式读文件,计算文件的CRC32校验和
		/***以RandomAccessFile方式读文件,计算文件的CRC32校验和***/
		public static long checknumRandomAccessFile(Path filename) throws IOException
		{
			try(RandomAccessFile file = new RandomAccessFile(filename.toFile(), "r")) 
			{
				CRC32 crc = new CRC32();
				long len = file.length();
				
				for (long i = 0; i < len; i++) {
					file.seek(i);
					int c = file.readByte();
					crc.update(c);
				}
				
				return crc.getValue();
			}
		}
  • 用MemMapFile【内存映象文件】方式读文件,计算文件的CRC32校验和
		/***以MemMapFile方式读文件,计算文件的CRC32校验和***/
		public static long checknumMemMapFile(Path filename) throws IOException
		{
			try(FileChannel channel = FileChannel.open(filename)) 
			{
				CRC32 crc = new CRC32();
				int len = (int)channel.size();
				MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, len);
				
				for (int i = 0; i < len; i++) {
					
					int c = buffer.get(i);
					crc.update(c);
				}
				
				return crc.getValue();
			}
		}

下面是“数据文件不同读入方式,计算文件的CRC32校验码,计算效率比较”测试文件的全部源代码:

/***数据文件不同读入方式,计算文件的CRC32校验码,计算效率比较***/
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.CRC32;
public class CRC32算法比较 {
	/***以InputStream方式读文件,计算文件的CRC32校验和***/
	public static long checknumInputStream(Path filename) throws IOException
	{
		try(InputStream stream = Files.newInputStream(filename)) 
		{
			CRC32 crc = new CRC32();
			int c;
			while ( (c = stream.read()) != -1) crc.update(c);
			
			return crc.getValue();
		}
	}
		
		/***以BufferedInputStream方式读文件,计算文件的CRC32校验和***/
		public static long checknumBufferedInputStream(Path filename) throws IOException
		{
			try(InputStream stream = new BufferedInputStream(Files.newInputStream(filename))) 
			{
				CRC32 crc = new CRC32();
				int c;
				while ( (c = stream.read()) != -1) crc.update(c);
				
				return crc.getValue();
			}
		}
		
		/***以RandomAccessFile方式读文件,计算文件的CRC32校验和***/
		public static long checknumRandomAccessFile(Path filename) throws IOException
		{
			try(RandomAccessFile file = new RandomAccessFile(filename.toFile(), "r")) 
			{
				CRC32 crc = new CRC32();
				long len = file.length();
				
				for (long i = 0; i < len; i++) {
					file.seek(i);
					int c = file.readByte();
					crc.update(c);
				}
				
				return crc.getValue();
			}
		}	
		
		/***以MemMapFile方式读文件,计算文件的CRC32校验和***/
		public static long checknumMemMapFile(Path filename) throws IOException
		{
			try(FileChannel channel = FileChannel.open(filename)) 
			{
				CRC32 crc = new CRC32();
				int len = (int)channel.size();
				MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, len);
				
				for (int i = 0; i < len; i++) {
					
					int c = buffer.get(i);
					crc.update(c);
				}
				
				return crc.getValue();
			}
		}
		
	public static void main(String[] args) throws IOException 
	{
		Path filename = Paths.get("D:\\Temp\\大约在冬季.mp3"); //3M
		//Path filename = Paths.get("D:\\Temp\\三步舞曲.mp3"); //12M
		System.out.println("InputStream");
		long start =  System.currentTimeMillis();
		long crcValue = checknumInputStream(filename);
		long end =  System.currentTimeMillis();
		System.out.println("CRC32:	"+Long.toHexString(crcValue));
		System.out.println("耗时:"+(end-start)+"微秒");
		
		System.out.println("BufferedInputStream");
		start =  System.currentTimeMillis();
		crcValue = checknumBufferedInputStream(filename);
		end =  System.currentTimeMillis();
		System.out.println("CRC32:	"+Long.toHexString(crcValue));
		System.out.println("耗时:"+(end-start)+"微秒");
		
		System.out.println("RandomAccessFile");
		start =  System.currentTimeMillis();
		crcValue = checknumRandomAccessFile(filename);
		end =  System.currentTimeMillis();
		System.out.println("CRC32:	"+Long.toHexString(crcValue));
		System.out.println("耗时:"+(end-start)+"微秒");
		
		System.out.println("MemMapFile");
		start =  System.currentTimeMillis();
		crcValue = checknumMemMapFile(filename);
		end =  System.currentTimeMillis();
		System.out.println("CRC32:	"+Long.toHexString(crcValue));
		System.out.println("耗时:"+(end-start)+"微秒");
	}
}

例程测试结果,每次测试数据会略有不同:

  • 3M大小音频文件的测试结果:

在这里插入图片描述

  • 12M大小音频文件的测试结果:

在这里插入图片描述

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值