2025-12-12 11:39:06 +08:00
|
|
|
|
using System;
|
2025-12-12 10:46:27 +08:00
|
|
|
|
using System.Collections.Generic;
|
2025-12-12 11:39:06 +08:00
|
|
|
|
using System.IO;
|
2025-12-12 10:46:27 +08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
|
|
namespace JoyD.Windows.CS
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 通用工具和方法
|
|
|
|
|
|
/// </summary>
|
2025-12-12 11:39:06 +08:00
|
|
|
|
public static class Utils
|
2025-12-12 10:46:27 +08:00
|
|
|
|
{
|
2025-12-12 11:39:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 使用CRC16/XMODEM算法计算字节数组的CRC16校验值
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="data">要计算CRC16的数据字节数组</param>
|
|
|
|
|
|
/// <param name="startIndex">计算的起始位置索引</param>
|
|
|
|
|
|
/// <param name="length">要计算的字节长度</param>
|
|
|
|
|
|
/// <returns>计算得到的CRC16校验值</returns>
|
2025-12-12 10:46:27 +08:00
|
|
|
|
public static ushort CalculateCRC16(byte[] data, int startIndex, int length)
|
|
|
|
|
|
{
|
|
|
|
|
|
ushort crc = 0;
|
|
|
|
|
|
int endIndex = startIndex + length;
|
|
|
|
|
|
for (int i = startIndex; i < endIndex && i < data.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
crc ^= (ushort)(data[i] << 8);
|
|
|
|
|
|
for (int j = 0; j < 8; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((crc & 0x8000) != 0)
|
|
|
|
|
|
crc = (ushort)((crc << 1) ^ 0x1021);
|
|
|
|
|
|
else
|
|
|
|
|
|
crc <<= 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return crc;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-12-12 11:39:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 使用CRC32-MPEG2算法计算字节数组的CRC32校验值
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="data">要计算CRC32的数据字节数组</param>
|
|
|
|
|
|
/// <returns>计算得到的CRC32校验值</returns>
|
2025-12-12 10:46:27 +08:00
|
|
|
|
public static uint CalculateCRC32(byte[] data)
|
|
|
|
|
|
{
|
2025-12-23 09:57:00 +08:00
|
|
|
|
return CalculateCRC32(data, 0xFFFFFFFF);
|
2025-12-12 10:46:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-12 11:39:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 支持增量计算的CRC32-MPEG2算法实现
|
|
|
|
|
|
/// </summary>
|
2025-12-23 09:57:00 +08:00
|
|
|
|
/// <param name="crc">上次CRC值(用于增量计算,首次为0xFFFFFFFF)</param>
|
2025-12-12 11:39:06 +08:00
|
|
|
|
/// <param name="data">要计算CRC32的数据字节数组</param>
|
|
|
|
|
|
/// <returns>计算得到的CRC32校验值</returns>
|
2025-12-23 09:57:00 +08:00
|
|
|
|
public static uint CalculateCRC32(byte[] data, uint crc = 0xFFFFFFFF)
|
2025-12-12 10:46:27 +08:00
|
|
|
|
{
|
|
|
|
|
|
uint polynomial = 0x04C11DB7;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < data.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
crc ^= (uint)data[i] << 24;
|
|
|
|
|
|
for (int j = 0; j < 8; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((crc & 0x80000000) != 0)
|
|
|
|
|
|
crc = (crc << 1) ^ polynomial;
|
|
|
|
|
|
else
|
|
|
|
|
|
crc <<= 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return crc;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-12 11:39:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 通过文件路径计算文件的CRC32校验值
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="filePath">文件的完整路径</param>
|
|
|
|
|
|
/// <returns>计算得到的CRC32校验值</returns>
|
|
|
|
|
|
/// <exception cref="ArgumentException">当文件路径为空或无效时抛出</exception>
|
|
|
|
|
|
/// <exception cref="FileNotFoundException">当指定路径的文件不存在时抛出</exception>
|
|
|
|
|
|
/// <exception cref="IOException">当文件读取失败时抛出</exception>
|
2025-12-12 10:46:27 +08:00
|
|
|
|
public static uint CalculateFileCRC32(string filePath)
|
|
|
|
|
|
{
|
|
|
|
|
|
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
|
|
|
|
|
{
|
|
|
|
|
|
return CalculateCRC32(fs);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-12 11:39:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 通过已打开的文件流计算文件的CRC32校验值
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="fs">已打开的文件流</param>
|
|
|
|
|
|
/// <returns>计算得到的CRC32校验值</returns>
|
|
|
|
|
|
/// <exception cref="ArgumentNullException">当文件流为null时抛出</exception>
|
|
|
|
|
|
/// <exception cref="IOException">当文件读取失败时抛出</exception>
|
2025-12-12 10:46:27 +08:00
|
|
|
|
public static uint CalculateCRC32(FileStream fs)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint crc = 0xFFFFFFFF;
|
|
|
|
|
|
uint polynomial = 0x04C11DB7;
|
|
|
|
|
|
|
|
|
|
|
|
// 保存当前位置
|
|
|
|
|
|
long originalPosition = fs.Position;
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 重置到文件开头
|
|
|
|
|
|
fs.Seek(0, SeekOrigin.Begin);
|
|
|
|
|
|
|
|
|
|
|
|
byte[] buffer = new byte[4096];
|
|
|
|
|
|
int bytesRead;
|
|
|
|
|
|
|
|
|
|
|
|
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < bytesRead; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
crc ^= (uint)buffer[i] << 24;
|
|
|
|
|
|
for (int j = 0; j < 8; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((crc & 0x80000000) != 0)
|
|
|
|
|
|
crc = (crc << 1) ^ polynomial;
|
|
|
|
|
|
else
|
|
|
|
|
|
crc <<= 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
// 恢复到原始位置
|
|
|
|
|
|
fs.Seek(originalPosition, SeekOrigin.Begin);
|
|
|
|
|
|
}
|
|
|
|
|
|
return crc;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-12 11:39:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 将字节数组转换为Base64编码的字符串
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="data">要转换的字节数组</param>
|
|
|
|
|
|
/// <returns>Base64编码的字符串</returns>
|
|
|
|
|
|
/// <exception cref="ArgumentNullException">当输入数据为null时抛出</exception>
|
2025-12-12 10:46:27 +08:00
|
|
|
|
public static string ByteArrayToBase64(byte[] data)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Convert.ToBase64String(data);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-12 11:39:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 将Base64编码的字符串转换为字节数组
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="base64">Base64编码的字符串</param>
|
|
|
|
|
|
/// <returns>转换后的字节数组</returns>
|
|
|
|
|
|
/// <exception cref="ArgumentNullException">当输入字符串为null时抛出</exception>
|
|
|
|
|
|
/// <exception cref="FormatException">当输入字符串不是有效的Base64格式时抛出</exception>
|
2025-12-12 10:46:27 +08:00
|
|
|
|
public static byte[] Base64ToByteArray(string base64)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Convert.FromBase64String(base64);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|