在 C# 中是否有等同于 mmap.mmap.rfind 的东西?

Is there an equivalent to mmap.mmap.rfind in C#?

在 C# 中查看内存映射文件时,很难确定如何快速向前和向后搜索文件。我的目标是用语言重写以下函数,但找不到像下面使用的 findrfind 方法那样的东西。在 C# 中有没有一种方法可以使用特定的子字符串快速搜索内存映射文件?

#! /usr/bin/env python3
import mmap
import pathlib


# noinspection PyUnboundLocalVariable
def drop_last_line(path):
    with path.open('r+b') as file:
        with mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as search:
            for next_line in b'\r\n', b'\r', b'\n':
                if search.find(next_line) >= 0:
                    break
            else:
                raise ValueError('cannot find any line delimiters')
            end_1st = search.rfind(next_line)
            end_2nd = search.rfind(next_line, 0, end_1st - 1)
        file.truncate(0 if end_2nd < 0 else end_2nd + len(next_line))

Is there a way in C# to quickly search a memory-mapped file using a particular substring?

Do you know of any way to memory-map an entire file in C# and then treat it as a byte array?

是的,将整个文件映射到视图然后将其读入单个 byte 数组非常容易,如以下代码所示:

static void Main(string[] args)
{
    var sourceFile=  new FileInfo(@"C:\Users\Micky\Downloads180112.zip");
    int length = (int) sourceFile.Length;  // length of target file

    // Create the memory-mapped file.
    using (var mmf = MemoryMappedFile.CreateFromFile(sourceFile.FullName,
                                                     FileMode.Open, 
                                                     "ImgA"))
    {
        var buffer = new byte[length]; // allocate a buffer with the same size as the file

        using (var accessor = mmf.CreateViewAccessor())
        {
            var read=accessor.ReadArray(0, buffer, 0, length); // read the whole thing
        }

        // let's try searching for a known byte sequence.  Change this to suit your file
        var target = new byte[] {71, 213, 62, 204,231};

        var foundAt = IndexOf(buffer, target);

    }
}

我似乎无法在 MarshalArray 中找到任何字节搜索方法,但您可以使用此搜索算法 courtesy 社交 MSDN 作为开始:

private static int IndexOf2(byte[] input, byte[] pattern)
{
    byte firstByte = pattern[0];
    int  index     = -1;

    if ((index = Array.IndexOf(input, firstByte)) >= 0)
    {
        for (int i = 0; i < pattern.Length; i++)
        {
            if (index + i  >= input.Length ||
                pattern[i] != input[index + i]) return -1;
        }
    }

    return index;
}

...甚至这个更详细的示例(也由 Social MSDN 提供,相同 link)

public static int IndexOf(byte[] arrayToSearchThrough, byte[] patternToFind)
{
    if (patternToFind.Length > arrayToSearchThrough.Length)
        return -1;
    for (int i = 0; i < arrayToSearchThrough.Length - patternToFind.Length; i++)
    {
        bool found = true;
        for (int j = 0; j < patternToFind.Length; j++)
        {
            if (arrayToSearchThrough[i + j] != patternToFind[j])
            {
                found = false;
                break;
            }
        }
        if (found)
        {
            return i;
        }
    }
    return -1;
}