【问题标题】:Is there an equivalent to mmap.mmap.rfind in C#?C# 中是否有等效于 mmap.mmap.rfind 的内容?
【发布时间】:2018-01-23 16:05:34
【问题描述】:

在 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))

【问题讨论】:

标签: c# python-3.x translate


【解决方案1】:

在 C# 中有没有一种方法可以使用特定的子字符串快速搜索内存映射文件?

你知道有什么方法可以在 C# 中对整个文件进行内存映射,然后将其视为字节数组吗?

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

static void Main(string[] args)
{
    var sourceFile=  new FileInfo(@"C:\Users\Micky\Downloads\20180112.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 中找不到任何字节搜索方法,但您可以使用 Social MSDN 的此搜索算法 courtesy 作为开始:

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 提供,相同链接)

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;
}

【讨论】:

  • 您的搜索算法不是最好的算法之一。使用 Boyer-Moore algorithm 您可能会看到 5-8 倍的加速。
  • 感谢示例代码!我可能会再等一天再接受答案,看看是否有其他想法。
  • @ScottChamberlain 那是因为它不是我的
  • @MickyD 我知道,我想说的是找到一个 Boyer-Moore 的例子并展示它会更好。
猜你喜欢
  • 2018-05-01
  • 1970-01-01
  • 2018-11-09
  • 2018-04-09
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多