Я бы предложил разбить файл на блоки. Все блоки имеют одинаковую длину при загрузке, но длина каждого блока может измениться, если пользователь редактирует эти блоки. Это позволяет избежать перемещения 100 мегабайт данных, если пользователь вставляет один байт впереди.
Чтобы управлять блоками, просто поместите их в список вместе со смещением каждого блока. Если пользователь изменяет длину блоков, вы должны обновлять только смещения блоков после этого. Чтобы найти смещение, вы можете использовать бинарный поиск.
Размер файла: 100 МиБ
Размер блока: 16 КБ
блоков: 6400
Нахождение смещения с использованием бинарного поиска (наихудший случай): 13 шагов
Модификация блока (наихудший случай): Копировать 16384 байта данных и обновить 6400 смещений блока
Изменение блока (средний регистр): копировать 8192 байта данных и обновлять 3200 смещений блока
Размер блока 16 КБ - это случайный пример - вы можете сбалансировать стоимость операций, выбрав размер блока, возможно, исходя из размера файла и вероятности операций. Выполнение простой математики даст оптимальный размер блока.
Загрузка будет довольно быстрой, потому что вы загружаете блоки фиксированного размера, и сохранение также должно работать хорошо, потому что вам придется писать несколько тысяч блоков, а не миллионы отдельных строк. Вы можете оптимизировать загрузку, загружая блоки только по требованию, и вы можете оптимизировать сохранение, сохраняя только те блоки, которые были изменены (содержимое или смещение).
Наконец, реализация не будет слишком сложной. Вы можете просто использовать класс StringBuilder
для представления блока. Но это решение не будет работать хорошо для очень длинных линий с длинами, сопоставимыми с размером блока или больше, потому что вам придется загружать много блоков и отображать только небольшие части, а остальное будет слева или справа от окна. Я предполагаю, что в этом случае вам придется использовать двумерную модель разбиения.