Старший бит здесь: вы пытаетесь решить проблему с базой данных, используя текстовые файлы. Базы данных предназначены для решения больших проблем с данными;текстовые файлы, как вы обнаружили, ужасны при произвольном доступе. Используйте базу данных, а не текстовый файл .
Если вы одержимы использованием текстового файла, вам нужно воспользоваться тем, что вы знаете овероятные параметры проблемы . Например, если вы знаете, что, как вы подразумеваете, существует ~ 1 млн строк, каждая строка составляет ~ 1 КБ, а набор извлекаемых строк составляет ~ 0,1% от общего количества строк, тогда вы можете найти эффективное решение, такое какthis:
- Создайте набор, содержащий номера строк для чтения. Набор должен быстро проверять членство.
- Создайте словарь, который сопоставляет номера строк и их содержимое. Это должно быть быстро, чтобы искать по ключу и быстро добавлять новые пары ключ / значение.
- Читайте каждую строку файла по одной;если номер строки находится в наборе, добавьте содержимое в словарь.
- Теперь выполните итерацию списка номеров строк и сопоставьте содержимое словаря;теперь у нас есть последовательность строк.
- Дамп этой последовательности в файл назначения.
У нас есть пять операций, так что, надеюсь, это около пяти строк кода.
void DoIt(string pathIn, IEnumerable<int> lineNumbers, string pathOut)
{
var lines = new HashSet<int>(lineNumbers);
var dict = File.ReadLines(pathIn)
.Select((lineText, index) => new KeyValuePair<int, string>(index, lineText))
.Where(p => lines.Contains(p.Key))
.ToDictionary(p => p.Key, p => p.Value);
File.WriteAllLines(pathOut, lineNumbers.Select(i => dict[i]));
}
ОК, получил в шесть. Довольно хорошо.
Обратите внимание, что я использовал все эти предположения; если допущения нарушаются, это перестает быть хорошим решением . В частности, мы предполагаем, что словарь будет небольшим по сравнению с размером входного файла. Если это не так, тогда вам понадобится более изощренная методика для повышения эффективности.
И наоборот, можем ли мы извлечь дополнительную эффективность? Да, при условии, что мы знаем факты о вероятных входных данных . Предположим, например, что мы знаем, что один и тот же файл будет повторяться несколько раз, но с разными наборами номеров строк, но эти наборы, вероятно, будут перекрываться. В этом случае мы можем повторно использовать словари вместо их восстановления. То есть, предположим, что предыдущая операция оставила Dictionary<int, string>
, вычисленную для строк (10, 20, 30, 40) и файла X. Если затем приходит запрос для строк (30, 20, 10) для файла X, мы ужеиметь словарь в памяти.
Ключевым моментом, который я хочу донести в этом ответе, является то, что вы должны знать кое-что о входных данных, чтобы построить эффективное решение;чем больше ограничений вы можете сформулировать для входных данных, тем более эффективное решение вы сможете создать. Воспользуйтесь всеми своими знаниями о проблемной области.