Чего мелочиться, надо начинать не с байтов, а с битов
Допустим, что у нас есть лог-файл размером L=6980914 байтов.
Чтобы адресовать отдельный байт в нём, нужно IndexLength = log(L;2) = 23 бита (то есть 3 байта, и 1 бит в запасе)
Чтобы указать длину сегмента, потребуется столько же
допустим, что в кодировке нет символов, длиннее, чем 4 байта.
Если файл состоит из ровно-четырёхбайтовых символов, то
их количество (SymbolsSetSizeEstimate) будет ограничено сверху (если символы не повторяются) min (L / 4, 2^(8*4)) = L/4
если из трёхбайтовых - то min(L/3, 2^(8*3)) = 2^24 (LOG(2^24,10) ~= 7, т.е. ~1 миллион)
двухбайтовых min(L/2, 2^(8*2)) = 2^16
однобайтовых min(L/1, 2^(8*1)) = 2^8
суммарное число различных возможных символов не превышает суммы этих ограничений.
поэтому выделим массив из трёхбайтных структур (ну, можно было и из 23-х битовых)
трёхбайтные они потому, что будут подсчитывать количество вхождений конкретного символа,
а количество вхождений не превышает общего количества символов, то есть как и длина файла умещается в IndexLength битов
массив выделили, длиной SymbolsSetSizeEstimate структур или SymbolsSetSizeEstimate * IndexLength битов,
посчитаем туда актуальную частоту вхождения символов
есть класс BitArray с методом Item[Int32] - можно ли его здесь применить?
то есть, что больше, 2^32 или IndexLength * sum(min(L/1,2^(8*1));min(L/2,2^(8*2));min(L/3,2^(8*3));min(L/4,2^(8*4)))
SymbolsSetSizeEstimate * IndexLength = 4137991 * 23. Это у нас 27 битов, меньше чем 31,
так что класс BigArray можно попробовать использовать
итак, насчитали мы количество символов, написали класс, который к этим битовым счётчикам предоставляет
типизированный доступ к счетчику по коду символа
Что дальше?
имея счётчики, сортируем символы по частоте встречаемости (зачем?
ну, можно потом построить дерево хаффмена, и перекодировать текст во внутреннюю кодировку, только зачем?
и делать это нужно после того, как построен вариант парсинга текста на символы Unicode)
перекодированный текст будет короче в битах, и возможно, что индексы для него будут компактнее (но ненамного же? надо проверять)
глядя на таблицы unicode надо пройтись по тексту и построить список вариантов разбиения
(таких вариантов может быть очень много? ну да, например, если есть последовательность символов, не входящих в стандарт.
про такие символы, наверное, неизвестно какой они длины - надо узнать по-подробнее)
собственно возможных вариантов разбиения два - с Byte Order Mark и без него,
причём можно однозначно выбрать, глядя на первый символ
если есть символы, не определённые в стандарте unicode...
(а так вообще может быть? Ну из-за чего-то же сейчас возникает ошибка с mdash... ну так разберись с ней)
то единственное, что можно сделать - выдать сообщение о первой ошибке
ну или надо грамматику писать с error-правилами
ну или парсер брать многовариантный
как из многих вариантов выбрать один? Подбирать вариант наиболее полно описывающий исходный текст?