【问题标题】:C# Binary Search + ReplaceC# 二进制搜索 + 替换
【发布时间】:2019-04-21 05:16:52
【问题描述】:

我如何搜索指定的字节数组并将从开头的所有内容替换为该字节数组(包含)

基本上我有我的模式要找到

byte[] find = { 0x00, 0x48, 0x00 };

byte[] ddsHeaderDXT1 = { 0x44, 0x44, 0x53, 0x20, 0x7C, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x56, 0x54, 0x54, 0x06, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x44, 0x58, 0x54, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 };

我想做的是搜索我的find 数组,一旦找到,选择从文件开头到包含的find 数组的所有字节,并将所有这些替换为我的ddsHeaderDXT1 数组。 文件可能很大,但模式总是在开头(少于 500 个首字节),并不总是在相同的偏移量处,并且只能找到一次。

我已经尝试过 rene 的代码here,但它什么也没做。 我也从 OpenFileDialog 获取我的文件并读取它的字节

byte[] src = File.ReadAllBytes(ofdFilePath);

【问题讨论】:

  • "我已经在这里尝试了 rene 的代码,但它什么也没做"。我怀疑它没有做任何事情。您到底尝试了哪些方法,为什么没有按照您的预期进行?
  • 如果你想从头替换所有东西并且ddsHeaderDXT1比找到的位置短,你期望会发生什么?
  • @elgonzo 我试过ReplaceBytes(src, find, ddsHeaderDXT1);,它只是没有更改我的文件,但没有错误,也许我做错了什么。 @OlivierJacot-Descombes 然后我只想插入并增加文件大小¯_(ツ)_/¯
  • 我的意思是,ddsHeaderDXT1 的长度为 110。如果您在位置 400 找到模式,则可以用它填充索引 0 .. 109 处的字节。你打算用什么来填充字节 110 .. 399?
  • @OlivierJacot-Descombes 然后我只想删除其余部分

标签: c# search replace byte


【解决方案1】:

以下应该可以解决问题:

public static bool TryFindAndReplace<T>(
    T[] source,
    T[] pattern,
    T[] replacement,
    out T[] newArray)
{
    if (source == null)
        throw new ArgumentNullException(nameof(source));

    if (pattern == null)
        throw new ArgumentNullException(nameof(pattern));

    if (replacement == null)
        throw new ArgumentNullException(nameof(replacement));

    newArray = null;

    if (pattern.Length > source.Length)
        return false;

    for (var start = 0; 
         start < source.Length - pattern.Length + 1; 
         start += 1)
    {
        var segment = new ArraySegment<T>(source, start, pattern.Length);

        if (Enumerable.SequenceEqual(segment, pattern))
        {
            newArray = replacement.Concat(source.Skip(start + pattern.Length))
                                  .ToArray();
            return true;
        }
    }

    return false;
}

易于阅读,因此易于理解。它无论如何都不是最快的解决方案,但事情需要尽可能快,而不是更快。

如果您需要更高性能的实现,可以从此处进行优化。

【讨论】:

  • 感谢您的回答,我对 c# 还是有点陌生​​, 是什么意思,我该如何使用它?
  • @Asval 它是泛型的。它使您能够将此方法用于任何类型,而不仅仅是字节。将T 视为“在此处插入类型”
  • 哦,好吧,我明白了,它很聪明 :) 谢谢你的代码就像一个魅力:D
猜你喜欢
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 2011-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 2014-11-02
相关资源
最近更新 更多