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 шт):

Автор решения: A K

Для начала напишите наивную реализацию, она у вас неправильно реализована: должно быть два цикла, один внутри другого. (А у вас один цикл, это не работает)

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 Мб можно и поискать более эффективные техники чтения огромных файлов, но вы пока с таким поработайте, освойтесь.

→ Ссылка
Автор решения: MBo

Введите переменную текущего состояния:

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;
        }     
    }
→ Ссылка