【问题标题】:How to reliably regex a Base64String如何可靠地正则表达式 Base64String
【发布时间】:2016-10-27 19:02:08
【问题描述】:

所以基本上我正在编写一个在二进制文件中查找 PNG 文件的应用程序。它通过将文件中的整个二进制文件读入字节数组,然后使用 Convert.ToBase64String 方法将其转换为字符串,然后使用匹配 PNG 的标头信息和结束块的正则表达式来查找图像。问题是使用 ToBase64String 方法会根据字节数组的长度生成截然不同的输出,而 MSDN 上的文档似乎没有详细说明。无论如何,这是我的意思的一个例子。

 byte[] somebytes = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };

 Console.WriteLine(Convert.ToBase64String(somebytes));

如果我跳过一个字节,现在这种情况下的输出是“AQIDBAUGBwg=”...

 byte[] somebytes = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };

 somebytes = somebytes.Skip(1).ToArray();

 Console.WriteLine(Convert.ToBase64String(somebytes));

现在的输出是“AgMEBQYHCA==”,所以几乎每个字符都与上一个示例相比发生了变化。

那么,我是在此处对二进制文件进行正则表达式的错误路径无可救药地走错了路,还是有一种方法(可能通过填充?)我可以保证这些转换的一致性?

更新: 根据我收集到的反馈,我似乎应该离开正则表达式解决方案,自己手动搜索开始和结束字节序列。不知道为什么我被否决了,因为我只是想了解为什么我的其他解决方案确实有效,而且似乎没有关于这个主题的任何其他帖子。无论如何,感谢大家的快速反馈。完成后我会发布用于查找图像的算法,以防它可能对其他人有益。

【问题讨论】:

  • 是的,你是。做base64然后试图找到标题是没有意义的。为什么不直接在二进制文件中查找?或者,如果您必须使用十六进制来保持一致性
  • "它通过将文件中的整个二进制文件读入字节数组,然后使用 Convert.ToBase64String 方法将其转换为字符串,然后使用匹配 PNG 标头的正则表达式来完成此操作信息和结束块以查找图像。” 什么...?你有一个字节数组,所以搜索字节数组。
  • 至于为什么会改变,是因为你在移动数组。 Base64 一次占用 6 位并转换为一个字符。如果你移动一个字节(8 位),那么你将得到完全不同的字符。
  • @Thermonuclear 这是一个糟糕的主意,尤其是,如果您想添加对其他文件格式的支持。只需在字节数组中搜索适当的格式签名即可。
  • 删除的答案是正确的。您需要检查图像的字节,而不是将其转换为其他内容并尝试以其他方式解析它。

标签: c# regex binaryfiles


【解决方案1】:

您在 cmets 中确认您正在尝试从 C# 结构化文件(EXE 或 DLL)中提取资源。您可以使用反射方法将它们拉出来:GetManifestResourceStream、GetManifestResourceNames、GetManifestResourceInfo 是一个很好的起点。

【讨论】:

  • 感谢您,我一定会尝试解决这个问题。我可能仍会继续手动读取字节,但理想情况下,如果图像替换器不仅仅适用于 .Net 二进制文件,但这些信息确实非常有用!
  • @Thermonuclear,本机 C++ 二进制文件也是结构化的,并且有用于处理资源的 api。你不应该尝试自己做这件事,因为它比你想象的更复杂。如果当前 PNG 是 1000 字节,而您想用 1010 字节替换它怎么办?您将覆盖代码/其他资源。 API 会为您解决这些问题。
  • 我的应用程序最初只允许对等于或小于被替换的原始图像的图像进行图像替换,从而避免了该问题,至少当我手动对 WPF 应用程序执行此操作时它起作用了。但是,如果这些 API 让我能够将图像换成更大的图像,这确实给了我一个非常有说服力的理由来重新考虑我的能力范围。
  • 所以在玩过“GetManifest”反射方法后,我看不出如何更改资源。我只看到“Get”方法,当我使用 GetManifestResourceStream 获取包含图像的流时,流的“CanWrite”属性为“false”。如果我错了,请纠正我,但我看不到如何使用反射设置或修改清单资源流。
【解决方案2】:

正如这里所承诺的,我编写的逻辑是在二进制文件中查找图像以防它可能对其他人有所帮助。不过,我最终可能会使用 SledgeHammers 方法,但对我来说很重要的是,我也能够使用这种方法来处理它。

public class BinarySearch
{
    public static IEnumerable<byte[]> Match(byte[] source, byte[] beginningSequence, byte[] endSequence)
    {
        int index = 0;

        IList<byte[]> matches = new List<byte[]>();

        while (index < source.Length)
        {
            var startIndex = FindSequence(source, beginningSequence, index);

            if (startIndex >= 0)
            {
                var endIndex = FindSequence(source, endSequence, startIndex + beginningSequence.Length);

                if (endIndex >= 0)
                {
                    var length = (endIndex - startIndex) + endSequence.Length;
                    var buffer = new byte[length];

                    Array.Copy(source, startIndex, buffer, 0, length);

                    matches.Add(buffer);

                    index = endIndex + endSequence.Length;
                }
                else
                {
                    index = source.Length;
                }
            }
            else
            {
                index = source.Length;
            }
        }

        return matches;
    }

    private static int FindSequence(byte[] bytes, byte[] sequence, int startIndex = 0)
    {
        int currentIndex = startIndex;
        int sequenceIndex = 0;
        bool found = false;

        while (!found && currentIndex < bytes.Length)
        {
            if (bytes[currentIndex] == sequence[sequenceIndex])
            {
                if (sequenceIndex == (sequence.Length - 1))
                {
                    found = true;
                }
                else
                {
                    sequenceIndex++;
                }
            }
            else
            {
                currentIndex -= sequenceIndex;
                sequenceIndex = 0;
            }

            currentIndex++;
        }

        return found ? (currentIndex - sequence.Length) : -1;
    }
}

这是一个用于 PNG 文件的示例。

var imageHeaderStart = new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00 };

var imageEOF = new byte[] { 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 };

var matches = BinarySearch.Match(binaryData, imageHeaderStart, imageEOF);

我会在 Github 项目完成后添加一个链接,以防有人对我的“完整”实现感兴趣。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 2018-03-21
    • 2011-12-02
    相关资源
    最近更新 更多