C# 在表示字符串的大字节数组中寻找子数组

Posted

技术标签:

【中文标题】C# 在表示字符串的大字节数组中寻找子数组【英文标题】:C# looking for subarrays in large byte array representing strings 【发布时间】:2021-12-22 05:13:37 【问题描述】:

在我的应用程序中,我需要打开一个文件,查找一个标签,然后根据该标签执行一些操作。 但!文件内容将每个char/0 交替,因此文本“CODE”变为0x43 0x00 0x4F 0x00 0x44 0x00 0x45 0x00(以十六进制字节表示)。

问题在于终结符也是 /0 ,因此带有终结符的“CODE123”看起来像这样:

0x43 0x00 0x4F 0x00 0x44 0x00 0x45 0x00 0x31 0x00 0x32 0x00 0x33 0x00 0x00 0x00

由于/0 是空字符串终止符,如果我使用File.ReadAllText() 我只会得到垃圾, 所以我尝试使用File.ReadAllBytes(),然后清除每个字节等于0。 这让我获得了可读的文本,但随后我丢失了有关数据何时结束的信息,即如果文件中有 CODE123[terminator]PROP456[terminator]blablabla 我最终得到 CODE123PROP456blablabla。

所以我决定将文件内容作为byte[] 获取,然后寻找另一个byte[] 用CODE-with-/0-inside 数据初始化。这理论上应该可行,但由于数据数组相当大(大约 150 万个元素),这需要的时间太长了。

蛋糕上的最后一颗樱桃是我正在寻找多次出现的 CODE 标签,所以我不能一找到就停下来。

我尝试修改此处作为答案发布的 LINQ:Find the first occurrence/starting index of the sub-array in C# 如下:

    var indices = (from i in Enumerable.Range(0, 1 + x.Length - y.Length)
                          where x.Skip(i).Take(y.Length).SequenceEqual(y)
                          select (int?)i).ToList();

但是,一旦我尝试枚举结果,它就会陷入困境。

所以,我的问题是:我怎样才能有效地在一个大数组中找到多个子数组?谢谢

【问题讨论】:

在其他地方查看我的答案,其中解释了如何实现 Boyer-Moore 搜索二进制数据:***.com/a/37500883/106159 空值似乎不是空字符串终止符。您只需要使用正确的编码读取它,它们只是该编码字符的一部分。大概是某种 utf16,但您应该比我们更了解您的文件编码是什么。 ReadAllText 对编码有重载。 @Ralf 这正是问题所在:它们不是终止符,除非它们被用作一个,所以如果我尝试解释它们,我会得到垃圾(第一个被视为空字符串终止符,基本上破坏整个字符串解释),无论我尝试什么编码。 如果您使用 ReadAllText 和 Encoding.Unicode 阅读,您会得到一个带有字符串终止符的字符串来分隔各个子字符串。然后 Split 会给你一个单独的字符串数组。 我不太相信 ;) 您是否尝试过更改字节顺序的编码,例如 BigEndianUnicode?​​span> 【参考方案1】:

The wonderful Boyer-Moore algoryth suggested by Matthew Wilson 惊人地解决了我的问题。

然后我必须找到一个解决方案来查找实际的字符串终止,这看起来太特定于应用程序而对其他人有用,所以我没有发布它。如果您认为它可能有用,请告诉我,我会在这里发布:)

【讨论】:

以上是关于C# 在表示字符串的大字节数组中寻找子数组的主要内容,如果未能解决你的问题,请参考以下文章

十六进制字符串到字节数组 C# [重复]

java和c#的字节数组转换问题

在c#中对字节数组表示的Int32求和

在 C# 中组合两个或多个字节数组的最佳方法

字节数组中的字符串不会在 C# 中被修剪?

将字节数组转换为字符串在c#中不起作用