Оптимизация I/O операций для работы с большими текстовыми файлами (1Гб+) - C#
Формулировка задачи:
Доброго времени суток.
Подскажите каким образом можно оптимизировать I/O операций для работы с большими текстовыми файлами (1Гб+)
Мне поставили задачу считывать данные из файла, делить каждую строку на слова и далее записывать список слов в другой файл с указанием номеров строк где каждое из слов встречается в файле №1.
Человек давший задание предложил мне использовать другую структуру данных, чтобы оптимизировать чтение/запись. Какая из структур данных справиться с этой задачей лучше List<T>?
Буду благодарен за ссылки на статьи и литературу про оптимизацию I/O для текстовых файлов.
Класс представляющий слово
Вот метод в котором я построчно считываю файл и создаю список слов
Метод с помощью которого я записываю результат в другой файл
public class Word
{
public string Text { get; set; }
public List<int> LineNumbers { get; set; }
public Word()
{
LineNumbers = new List<int>();
}
}public List<Word> ReadFileAsync(string filePath)
{
// var watch = System.Diagnostics.Stopwatch.StartNew();
List<Word> words = new List<Word>();
int lineCount = 1;
try
{
using (StreamReader sr = new StreamReader(filePath))
{
string nextLine;
while ((nextLine = sr.ReadLine()) != null)
{
AddWordFromLineToWordList(SplitLineIntoWords(nextLine), words, lineCount);
lineCount++;
}
}
}
catch (Exception ex)
{
}
// watch.Stop();
// var elapsedMs = watch.ElapsedMilliseconds;
// Console.WriteLine(elapsedMs);
return words;
}public async Task WriteAsync(string path, List<Word> words)
{
DeleteFile(path);
CreateFile(path);
words.Sort(new WordComparer());
foreach (Word word in words)
{
await WriteWordsAndLineNumbersAsync(path, word);
}
}private async Task WriteWordsAndLineNumbersAsync(string path, Word word)
{
try
{
using (FileStream fs = new FileStream(path, FileMode.Append,
FileAccess.Write, FileShare.Write, 4096, useAsync: true))
{
using (StreamWriter sw = new StreamWriter(fs))
{
await sw.WriteAsync(word.Text + " ");
int size = word.LineNumbers.Count;
for (int i = 0; i < size; i++)
{
if (i < size - 1)
{
await sw.WriteAsync(word.LineNumbers[i] + ", ");
}
else
{
await sw.WriteAsync(word.LineNumbers[i].ToString());
}
}
sw.Write(Environment.NewLine);
}
}
}
catch (Exception ex)
{
}
}Решение задачи: «Оптимизация I/O операций для работы с большими текстовыми файлами (1Гб+)»
textual
Листинг программы
static void Main(string[] args)
{
string str = "1 The the quick, brown fox. r fox jumped over the lazy dog dog.The1 the1 quick1, brown1 fox1. fox1 jumped1 over1 the1 lazy1 dog1 dog1.";
Regex pattern = new Regex(
@"( [A-Za-z0-9]
([A-Za-z0-9])*
[A-Za-z0-9])",
RegexOptions.IgnorePatternWhitespace);
List<string> list1 = SplitLineIntoWords(str, pattern);
List<string> list2 = SplitLineIntoWords2(str);
for(int i = 0; i < list1.Count; ++i)
{
if(!list1[i].SequenceEqual(list2[i])) throw new Exception();
}
Stopwatch sw1 = Stopwatch.StartNew();
list1 = SplitLineIntoWords(str, pattern);
sw1.Stop();
Console.WriteLine($"SplitLineIntoWords {sw1.ElapsedTicks}");
Stopwatch sw2 = Stopwatch.StartNew();
list2 = SplitLineIntoWords2(str);
sw2.Stop();
Console.WriteLine($"SplitLineIntoWords2 {sw2.ElapsedTicks}");
Console.ReadKey();
GC.KeepAlive(list1);
GC.KeepAlive(list2);
}
public static unsafe List<string> SplitLineIntoWords2(string str)
{
List<string> list = new List<string>();
int index = 0;
bool flag = false;
int i = 0;
fixed (char* ptr = str)
{
for(i = 0; i < str.Length; ++i)
{
int n = ptr[i];
if((n >= 'a' && n <= 'z') || (n >= 'A' && n <= 'Z') || (n >= '0' && n <= '9'))
{
if(!flag)
{
flag = true;
index = i;
}
}
else
{
if(flag && i - index > 1)
{
list.Add(new string(ptr, index, i - index).ToLower());
}
flag = false;
index = i;
}
}
if(flag && i - index > 1)
{
list.Add(new string(ptr, index, i - index).ToLower());
}
}
return list;
}
public static List<string> SplitLineIntoWords(string lineText, Regex pattern)
{
List<string> lineWords = new List<string>();
foreach(Match m in pattern.Matches(lineText))
{
lineWords.Add(m.Groups[1].Value.ToLower());
}
return lineWords;
}
}