我想讀出檔案的標題并將其與給定的簽名進行比較。簽名的開頭可以有一個偏移量。
這是我目前的功能:
public FileTypeVerifyResult Verify(Stream stream)
{
stream.Position = 0;
var reader = new BinaryReader(stream);
var headerBytes = reader.ReadBytes(SignatureLength this.OffSet);
return new FileTypeVerifyResult
{
Name = Name,
Description = Description,
IsVerified = Signatures.Any(signature =>
headerBytes.Skip(this.OffSet).Take(signature.Length)
.SequenceEqual(signature)
)
};
}
這目前適用于一個偏移量,但存在可以具有多個偏移量的擴展。所以我的第一個想法是使OffSet屬性int[]具有所有偏移量,但我不知道這是否可以輕松構建到此 linq 運算式中。
此外,檔案可以具有偏移量any(或任何其他值,表示檔案中的任何位置,例如-1)。這樣的東西怎么可能內置?
uj5u.com熱心網友回復:
為了能夠處理更多的偏移量,這是我的解決方案:
protected List<int> OffSets { get; set; }
public int OffSetLength => OffSets.Max(m => m);
public FileTypeVerifyResult Verify(Stream stream)
{
stream.Position = 0;
var reader = new BinaryReader(stream);
var headerBytes = reader.ReadBytes(SignatureLength OffSetLength);
reader.Close();
return new FileTypeVerifyResult
{
Name = Name,
Description = Description,
IsVerified = Signatures.Any(signature =>
OffSets.Any(offSet =>
headerBytes.Skip(offSet).Take(signature.Length)
.SequenceEqual(signature))
)
};
}
我不認為我可以在不重寫所有內容的情況下獲得此函式中的 any/-1 偏移量。
uj5u.com熱心網友回復:
我認為在這種情況下,瑞士刀不是你想要的,Linq 對很多事情都有好處,但它確實沒有為手頭的問題增加任何價值恕我直言,因為撰寫這樣的查詢會使人的眼球流血,但是如果有的話,這是我對 LINQ 的稀疏使用對問題本身的看法:)
我允許自己扣除未提供的丟失物品??并稍微合理化命名。
public class FileType
{
public class FileTypeVerifyResult
{
public string Name { get; set; }
public string Description { get; set; }
public bool IsVerified { get; set; }
}
public class Signature
{
/// <summary>
/// Actual signature
/// </summary>
public byte[] Payload { get; set; }
public int Length { get => Payload.Length; }
public List<int> OffSets { get; set; }
}
public string Name { get; set; }
public string Description { get; set; }
public List<Signature> Signatures { get; set; }
public FileTypeVerifyResult Verify(Stream stream)
{
if (stream == null) throw new ArgumentException(nameof(stream));
if(stream.CanSeek)
stream.Position = 0;
else
//TODO: Consider if we need this: throw new ArgumentException("Stream does not support seek", nameof(stream));
var bytes = new byte[stream.Length];
int wasRead = stream.Read(bytes, 0, (int)stream.Length);
if (wasRead == 0) throw new ArgumentException("Unable to read from stream");
foreach (var signature in Signatures)
{
foreach(var offset in signature.OffSets)
{
if(offset == -1)
{
//TODO: read signature length from each position first 0, then 1 until what is left is less than length of signature and if it fits
return createResultObject(true);
}
var candidateBytes = new byte[signature.Length];
candidateBytes = bytes.Skip(offset).Take(signature.Length).ToArray();
// I'd not use linq, instead Array.Copy(bytes, offset, candidateBytes, 0, signature.Length);
if(signature.Payload.Equals(candidateBytes))
{
return createResultObject(true);
}
}
}
return createResultObject();
FileTypeVerifyResult createResultObject(bool isValid = false)
{
return new FileTypeVerifyResult
{
Name = Name,
Description = Description,
IsVerified = isValid
};
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/360038.html
