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