C# Как получить позиции нулевых байтов в массиве байт?
Есть массив байт который получается из файла. Размер до 100 Мбайт. Требуется получить начало и конец всех непрерывных областей заполненных нулями и размер которых больше 100 байт То есть в массиве встречаются такие вот области:
9F 00 A4 01 57 00 CD FE 52 FF 32 00 87 01 D1 00 F8
FE 05 FE AC FE B2 00 E8 00 CF FE 11 FD B1 FD 8E FF
53 00 D1 FD 2B FD 1F FE 33 FF 51 00 17 FF 78 FD 6A
FE 89 00 7B 01 3B 01 E3 FF 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 FF FF 00 00 04 00 02 00 00 00 FA FF 00
00 05 00 00 00 F5 FF FB FF 04 00 06 00 0F 00 FA FF
EC FF 02 00 09 00 02 00 FC FF F7 FF FB FF 06 00 04
00 02 00 F9 FF F0 FF FD FF FC FF 04 00 3E 00 F8 FF
C4 FF 06 00 13 00 1E 00 00 00 20 00 04 00 CB FF EB
FF 35 00 32 00 F9 FF E5 FF F5 FF 00 00 03 00 01 00
FE FF 04 00 04 00 0F 00 D0 FF DC FF 18 00 EA FF 1C
00 17 00 EC FF F9 FF DA FF FC FF 39 00 06 00 E0 FF
17 00 0C 00 1D 00 EF FF C6 FF 03 00 FF FF F5 FF 00
00 30 00 FA FF EB FF FE FF 10 00 EC FF
нужно получить offset начала этой области и его конец или длину этой области. написал следующий код:
int counter = 0;
int lastZeroByteIndex = 0;
byte[] bytes = File.ReadAllBytes(file);
for(int i = 0; i < bytes.Length; i++)
{
if (bytes[i] == 0x00)
{
counter++;
if (lastZeroByteIndex == i - 1 && counter > 100)
{
Debug.WriteLine($"{i}");
}
else if (lastZeroByteIndex != i - 1)
{
counter = 0;
}
lastZeroByteIndex = i;
}
}
Debug.WriteLine($"total: {counter}");
Console.ReadKey();
В выводе получаю индексы всех байт после превышения ста нулевых байт:
155
156
157
23185
23186
23187
23188
23189
23190
23191
23192
23193
23194
23195
23196
23197
75025
75026
75027
75028
Так как в файле эти области зачастую могут занимать 200-600 байт или даже больше, то хотелось бы получать индекс последнего байта 0x00 из этой области. Подскажите как это можно сделать? К примеру вывод LastZeroOffset:23197(индекс последнего байта в области) ZeroBytesCounter:113(количество подряд идущих нулевых байт в области)
Ответы (2 шт):
Для начала напишите наивную реализацию, она у вас неправильно реализована: должно быть два цикла, один внутри другого. (А у вас один цикл, это не работает)
for (int i = 0; i < bytes.Length; i++)
{
if(bytes[i] != 0x00)
continue;
var startZeroSeria = i;
var endZeroSeria = i + 1;
while(bytes[endZeroSeria] == 0x00)
{
endZeroSeria++;
}
if(endZeroSeria - startZeroSeria > 100)
{
// ....
}
i = endZeroSeria - 1;
}
Внутренний цикл я написал на while, просто сэкономил на переменных - можете через for сделать, не принципиально.
while(bytes[endZeroSeria] == 0x00)
{
endZeroSeria++;
}
Мы просто сдвигаем указатель на конец серии нулей, на выходе из цикла получим последний нулевой элемент.
Дальше делайте что угодно.
Вообще же, для 100 Мб можно и поискать более эффективные техники чтения огромных файлов, но вы пока с таким поработайте, освойтесь.
Введите переменную текущего состояния:
state = 0;
start = 0;
for(int i = 0; i < bytes.Length; i++)
{
if (bytes[i] == 0x00)
{
if (state > 0) {
start = i;
state = 0;
}
}
else {
if (state == 0 && i - start > 100)
вывод start, i - start
state = 1;
}
}