我正在开发一个项目,我从文件中读取数据,并且需要操作其中一些数据。
数据是二进制的,其中包含一些 ASCII 编码文本。 如果重要的话,数据也会以大尾数法保存。
我想要完成的是找到此数据中的模式并操纵该模式的部分内容。
示例:(09 49 6E 76 65 6E 74 6F 72 79 0A 00 00 00 02 01 00)
这代表数字 9,表示库存中有多少个字母,后面跟着不带引号的 ASCII“库存”。 “0A”标记该 ASCII 文本的结尾,后面跟着 00 00 00 02 标记我们的库存“2”的大小。 “01 00”标志着整个库存区域的结束。
示例2:(04 53 6C 6F 74 00 02 00)
这表示数字 4 表示插槽中有多少个字母,后面跟着不带引号的 ASCII“插槽”。 “00”是 ASCII 文本和槽号“02”之间的空格,后跟区域末尾“00”。
我需要在文件中找到这些模式和其他几个模式。 然后我需要修改部分模式并写入磁盘。
示例修改:(04 53 6C 6F 74 00 02 00)“从上方”更改为(04 53 6C 6F 74 00 07 00),将“插槽号‘02’更改为‘07’。
另一个需要注意的是,虽然我需要在不同大小、长度和包含的数据的文件中搜索多个模式,但这些模式的多个部分可能包含需要单独修改的不同数据,如下所示一个整体。
澄清一下:(库存、槽位、id、计数)- 被视为一个人的信息。
每个被记录的人可以有多个副本(库存、槽位、id、计数)。
我想向用户显示此信息,并为他们提供修改组中每个元素的选项。
我不是一个好的程序员,想学习,如果你有例子我很感激,如果你有建议请给。如果能简化一下就更好了,谢谢。 我现在正在进行一项工作,但现在陷入困境。如果您想看看我有什么,请告诉我。
我所拥有的摘要:将文件读入 byte[],然后将整个数组显示到控制台。就是这样。通过一些格式化和一些调试信息来定位我读入数组的 block 。
这是我在 Pastebin 上的代码的链接。 LINK
我意识到我没有得到所有出现的(库存、槽位、id、计数),我也需要解决这个问题。
编辑:示例 (09 49 6E 76 65 6E 74 6F 72 79 0A 00 00 00 02 01 00) 这是我正在读取的文件中的固定长度的二进制数据 block 。如前所述,09 代表字符串的长度。字符串后面的是 (0A 00 00 00 02 01 00) 其中重要的部分是 (02) 这是因为这是该二进制数据片中唯一发生变化的字节。 “02”代表“2”,表示该特定人员记录有 2 个(槽位、id、计数)实例。
(File)
(09 Inventory 0A 00 00 00 02 01 00) // Start of person 1's record with 2 instances.
(Slot)
(id)
(Count)
(Slot)
(id)
(Count)
(Rotation) // End of person 1's record
(09 Inventory 0A 00 00 00 04 01 00) // Start of person 2's record with 4 instances.
(Slot)
(id)
(Count)
(Slot)
(id)
(Count)
(Slot)
(id)
(Count)
(Slot)
(id)
(Count)
(Rotation) // End of person 2's record
(File End)
我的想法是,我想编辑“id”或通过添加到库存来增加插槽数量,并添加更多(插槽、id、计数)实例。
“id” - 包含项目 ID
“槽位” - 包含库存槽位编号
“计数” - 包含该槽中有多少项目。 编辑注意:如果我不清楚,请告诉我,再次感谢。
最佳答案
你说你不是一个好的程序员。然后我会提出一些基本建议。
首先,对于任何问题,将其分解。尝试将其分解为您可以解决的更简单的子问题,或者认为会更容易解决。您说您想检查文件中的模式,然后可能修改一些数据并将其写回。作为第一步,我想说这些是您需要解决的主要子问题,以便获得完整的解决方案。
- 读取文件
- 搜索二进制数据中的模式
- 进行修改
- 写出修改后的数据。
您主要关注“搜索模式”部分,因此我将集中对此进行进一步评论。所有其他部分也可能很棘手,但您可以自己解决它们,也可以在 stackoverflow 或其他地方寻找其他人如何解决它们的提示。
好的,现在,关于“搜索模式”。在我阅读你的描述时,
在我看来,字节数组中的第一个字节是文本长度。在 C# 代码中,可以像这样显式声明展示模式的数据数组:
byte[] data = new byte[] { 9, 0x49, 0x6E, 0x76, 0x65, 0x6E, 0x74,
0x6F, 0x72, 0x79, 0x0A, 0, 0, 0, 2, 1, 0 } ;
当然,您不会显式声明该数组。您将通过文件读取操作创建或填充数组。此时文件读取仍然是一个 Unresolved 问题,但没关系 - 您可以单独解决它。并且,效果是相同的 - 当您成功读取文件时,您将拥有一个类似于上面显式声明的数组的字节数组。
好的,现在你如何操作这些数据?第一个字节是字符串数据的长度。接下来的 N 个字节是字符串数据。然后你还有一些其他的东西。
您没有准确描述您想要进行哪些“修改”,但根据您提供的信息,应该很容易浏览数据。
如果你想获取数组中数据的“切片”,你可以这样做。
int length = (int) data[0];
byte[] s = new byte[length];
Array.Copy(data, 0, s, 0, length);
// now, s contains N bytes, representing the string
您可能想做的下一件事是从您切出的字节中获取实际的字符串。为此,请使用 the Encoding class :
String word = System.Text.Encoding.UTF8.GetString(s);
我不明白字符串数据后面的数据的模式。在某些情况下,它是 00
,在某些情况下,它是 0A
。
但也许您知道其中的模式。按照同样的方法,您可以遍历一条“记录”的所有数据。当您到达记录末尾时,然后重新开始并处理下一条记录。获取下一个“记录”的关键是知道要从文件中读取的数据中取出多大的数据片段。
这让我们回到“读取文件”子问题。从文件中获取适量数据的一种方法是仅读取第一个字节,然后再读取文件中的 N 个字节。 (参见System.IO.Stream.Read)。
byte[] size = new byte[1];
var fileStream = File.OpenRead(path);
int offset = 0;
int n;
n = fileStream.Read(size, offset, 1);
// size[0] now contains the byte of data indicating the number of bytes to follow
此时可以读取接下来的N个字节:
int length = (int)size[0];
byte[] stringData = new byte[length];
n = fileStream.Read(stringData, offset, length);
现在你可以获取字符串了。
String word = System.Text.Encoding.UTF8.GetString(stringData);
...等等。读取所有尾随字节。此时,fileStream
隐式保存的游标指向文件中的下一条记录。
关于c# - 如何在 C# 中的字节数组中查找字节模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11378691/