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;
+ }
+
+ }
+
+}