亲测可以实现检测7z的自解压,但是对于rar的自解压格式,最新版不支持,尝试修改回发现几乎检测成了exe文件,这显然是不正确的,其他版本未测试。
如下图所示,可以检测出自解压格式的7z文件,黑色显示。
直接上代码:
public class SelfExtractingChecker
{
public static bool Is7zOrRarSfx(string filePath)
{
try
{
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
// 检查RAR自解压文件签名
if (CheckRarSignature(fs))
{
return true;
}
// 检查7z自解压文件签名
if (Check7zSignature(fs))
{
return true;
}
}
}
catch
{
// 处理文件访问异常
return false;
}
return false;
}
private static bool CheckRarSignature(FileStream fs)
{
// RAR签名:"Rar!\x1A\x07\x00"(7字节)
byte[] rarSig = { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 };
// 常见偏移量(按优先级排序)
int[] possibleOffsets = { 0x200, 0x210, 0x400, 0x1000 };
foreach (int offset in possibleOffsets)
{
if (fs.Length > offset + rarSig.Length)
{
fs.Seek(offset, SeekOrigin.Begin);
byte[] buffer = new byte[rarSig.Length];
int bytesRead = fs.Read(buffer, 0, buffer.Length);
if (bytesRead == buffer.Length && buffer.SequenceEqual(rarSig))
{
return true;
}
}
}
return false;
}
private static bool Check7zSignature(FileStream fs)
{
// 7z签名:"7z\xBC\xAF\x27\x1C"(6字节)
byte[] sevenZipSig = { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C };
const int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int overlap = sevenZipSig.Length - 1;
int bytesRead;
long totalRead = 0;
fs.Seek(0, SeekOrigin.Begin);
while ((bytesRead = fs.Read(buffer, 0, bufferSize)) > 0)
{
// 检查当前缓冲区
for (int i = 0; i < bytesRead - overlap; i++)
{
bool match = true;
for (int j = 0; j < sevenZipSig.Length; j++)
{
if (i + j >= bytesRead || buffer[i + j] != sevenZipSig[j])
{
match = false;
break;
}
}
if (match)
{
return true;
}
}
// 处理边界情况:保留最后几个字节与下一块组合
if (bytesRead >= overlap)
{
Array.Copy(buffer, bytesRead - overlap, buffer, 0, overlap);
totalRead += bytesRead - overlap;
}
else
{
Array.Copy(buffer, 0, buffer, 0, bytesRead);
totalRead += bytesRead;
}
// 检查是否超过合理搜索范围(前20MB)
if (totalRead > 20 * 1024 * 1024)
{
break;
}
}
return false;
}
}
以上,谨此纪念。