From f878c7336eeeb03be9bcc1832d2a2e76c7a660cc Mon Sep 17 00:00:00 2001 From: Elivo Date: Mon, 28 Jul 2025 21:04:41 +0800 Subject: [PATCH] =?UTF-8?q?BytesUtility=EF=BC=9A=E5=A2=9E=E5=8A=A0=20CRC16?= =?UTF-8?q?=20=E6=96=B9=E6=B3=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apewer/BytesUtility.cs | 3 +++ Apewer/Internals/CRC16.cs | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 Apewer/Internals/CRC16.cs diff --git a/Apewer/BytesUtility.cs b/Apewer/BytesUtility.cs index d4b2d04..066efb9 100644 --- a/Apewer/BytesUtility.cs +++ b/Apewer/BytesUtility.cs @@ -1079,6 +1079,9 @@ namespace Apewer /// 获取 SHA512 值。 public static byte[] SHA512(this Stream stream, Action progress = null) => ComputeHash(stream, progress); + /// 计算 CRC16 校验和。 + public static ushort CRC16(this byte[] bytes) => Internals.CRC16.Instance.Compute(bytes); + #endregion } diff --git a/Apewer/Internals/CRC16.cs b/Apewer/Internals/CRC16.cs new file mode 100644 index 0000000..16f89e3 --- /dev/null +++ b/Apewer/Internals/CRC16.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Apewer.Internals +{ + + class CRC16 + { + + public static CRC16 Instance = new CRC16(); + + const ushort origin = 0xFFFF; + const ushort polynomial = 0xA001; + + ushort[] table = new ushort[256]; + + public CRC16() + { + ushort value, temp; + for (ushort i = 0; i < table.Length; ++i) + { + value = 0; + temp = i; + for (byte j = 0; j < 8; ++j) + { + if (((value ^ temp) & 0x0001) != 0) + { + value = (ushort)((value >> 1) ^ polynomial); + } + else + { + value >>= 1; + } + temp >>= 1; + } + table[i] = value; + } + } + + public ushort Compute(byte[] bytes) + { + ushort crc = origin; + for (int i = 0; i < bytes.Length; ++i) + { + byte index = (byte)(crc ^ bytes[i]); + crc = (ushort)((crc >> 8) ^ table[index]); + } + return crc; + } + + } + +}