因此,我没有一个单一的想法来解决这种情况,我有一个功能可以通过替换我想要的值来修补文件,但是我要修补的文件约为4.5GB。 这是功能:
private static readonly byte[] PatchFind = { 0x74, 0x72, 0x79 };
private static readonly byte[] PatchReplace = { 0x79, 0x72, 0x74 };
private static bool DetectPatch(byte[] sequence, int position)
{
if (position + PatchFind.Length > sequence.Length) return false;
for (int p = 0; p < PatchFind.Length; p++)
{
if (PatchFind[p] != sequence[position + p]) return false;
}
return true;
}
private static void PatchFile(string originalFile, string patchedFile)
{
// Ensure target directory exists.
var targetDirectory = Path.GetDirectoryName(patchedFile);
if (targetDirectory == null) return;
Directory.CreateDirectory(targetDirectory);
// Read file bytes.
byte[] fileContent = File.ReadAllBytes(originalFile);
// Detect and patch file.
for (int p = 0; p < fileContent.Length; p++)
{
if (!DetectPatch(fileContent, p)) continue;
for (int w = 0; w < PatchFind.Length; w++)
{
fileContent[p + w] = PatchReplace[w];
}
}
// Save it to another location.
File.WriteAllBytes(patchedFile, fileContent);
}
所以我如何实现与2GB +文件一起使用的功能。任何帮助将不胜感激。
答案 0 :(得分:3)
您的问题是File.ReadAllBytes
不会打开长度超过Int.MaxValue
的文件。不管文件有多大,仅将整个文件加载到内存中以仅扫描其是否存在模式都是不好的设计。您应将文件作为流打开,并使用扫描仪模式逐步浏览文件,并替换与模式匹配的字节。使用BinaryReader
的一种相当简单的实现:
static void PatchStream(Stream source, Stream target
, IList<byte> searchPattern, IList<byte> replacementPattern)
{
using (var input = new BinaryReader(source))
using (var output = new BinaryWriter(target))
{
var buffer = new Queue<byte>();
while (true)
{
if (buffer.Count < searchPattern.Count)
{
if (input.BaseStream.Position < input.BaseStream.Length)
buffer.Enqueue(input.ReadByte());
else
break;
}
else if (buffer.Zip(searchPattern, (b, s) => b == s).All(c => c))
{
foreach (var b in replacementPattern)
output.Write(b);
buffer.Clear();
}
else
{
output.Write(buffer.Dequeue());
}
}
foreach (var b in buffer)
output.Write(b);
}
}
您可以使用以下代码对文件进行调用:
PatchStream(new FileInfo(...).OpenRead(),
new FileInfo(...).OpenWrite(),
new[] { (byte)'a', (byte)'b', (byte)'c' },
new[] { (byte)'A', (byte)'B', (byte)'C' });