Многопоточная поиск и замена в ТХТ файле. Возможно?

  • Автор темы Автор темы toxass
  • Дата начала Дата начала

toxass

Client
Регистрация
18.03.2010
Сообщения
280
Реакции
12
Баллы
18
Есть ТХТ файл с разным контентом, необходимо найти и заменить порядка 100к строк.

Подскажите самый быстрый и многопоточный алгоритм решения этой задачи с помощью Зеннопостра.
 
Разделить файл на части, запустить замену во многопотоке другим шаблоном.
 
Есть ТХТ файл с разным контентом, необходимо найти и заменить порядка 100к строк.

Подскажите самый быстрый и многопоточный алгоритм решения этой задачи с помощью Зеннопостра.
Нечетко описана задача.
 
На самом деле 100к - это не кретичная цифра. Опишите подробнее, что именно Вам нужно. Не думаю, что эта процедура займёт много времени даже в один поток.
 
На самом деле 100к - это не кретичная цифра. Опишите подробнее, что именно Вам нужно. Не думаю, что эта процедура займёт много времени даже в один поток.

Конкретно. Файл, в котором нужно делать замены весит 300мб, в нем новости с разными ссылками, эти ссылки мне и нужно заменить на свои из заранее подготовленного списка: Сссылку1 заменить на Ссылку2 и так 100к строк. В 1 поток делает очень долго. Разбивать не могу.
 
Конкретно. Файл, в котором нужно делать замены весит 300мб, в нем новости с разными ссылками, эти ссылки мне и нужно заменить на свои из заранее подготовленного списка: Сссылку1 заменить на Ссылку2 и так 100к строк. В 1 поток делает очень долго. Разбивать не могу.
Насколько я знаю, многопоток тут не поможет, т.к. вы упрётесь в скорость работы диска и будет не быстрее, чем при однопотоке
 
Тут наверное проще будет сразу выгрузить весь файл в память, выполнить в нём замены и потом записать назад.
Памяти конечно отожрёт прилично сразу.
Делать такое многопотоком точно не вариант, будет только хуже.
Как вариант, если эти новости каким то образом отделяются одна от другой - брать их отдельно с удалением, обрабатывать и записывать в новый файл. Тогда можно и несколько потоков использовать.
 
Тут наверное проще будет сразу выгрузить весь файл в память, выполнить в нём замены и потом записать назад.
Памяти конечно отожрёт прилично сразу.
Делать такое многопотоком точно не вариант, будет только хуже.
Как вариант, если эти новости каким то образом отделяются одна от другой - брать их отдельно с удалением, обрабатывать и записывать в новый файл. Тогда можно и несколько потоков использовать.

ОЗУ 32 ГБ, но вот удалять тоже нельзя. Выходит только ждать?
 
Конкретно. Файл, в котором нужно делать замены весит 300мб, в нем новости с разными ссылками, эти ссылки мне и нужно заменить на свои из заранее подготовленного списка: Сссылку1 заменить на Ссылку2 и так 100к строк. В 1 поток делает очень долго. Разбивать не могу.
В 1 поток файл в 905Mb обрабатывает за 4-5 минут:

C#:
Развернуть Свернуть Копировать
//<a href="https://google.com">Click here</a>
var file_1 = @"F:\Tests\100k.txt";

//Hello from Zenno <a href="https://yandex.ru">Yandex Company</a> this is end of sentence
var file_2 = @"F:\Tests\10kk.txt"; //905mb

//Hello from Zenno <a href="https://google.com">Click here</a> this is end of sentence
var file_3 = @"F:\Tests\Result.txt";

//Регулярка для замены
var regex = new Regex(@"<a\ .*?</a>");

var links = File.ReadLines(file_1, Encoding.UTF8).ToList();
var lines = File.ReadLines(file_2, Encoding.UTF8);


var fs = new FileStream(file_3, FileMode.OpenOrCreate, FileAccess.Write);
var sw = new StreamWriter(fs, Encoding.UTF8);
sw.AutoFlush = true;

foreach(string line in lines)
{
    var changedStr = line;
    var mCount = regex.Matches(changedStr).Count;
   
    for(int i=0; i< mCount; i++)
    {
        if(links.Count > 0)
        {
            var link = links.ElementAt(0);
            links.RemoveAt(0);
            changedStr = regex.Replace(changedStr, link, i+1);
        }
    }   
    sw.WriteLine(changedStr);
}

sw.Close();
fs.Close();
 
В 1 поток файл в 905Mb обрабатывает за 4-5 минут:

C#:
Развернуть Свернуть Копировать
//<a href="https://google.com">Click here</a>
var file_1 = @"F:\Tests\100k.txt";

//Hello from Zenno <a href="https://yandex.ru">Yandex Company</a> this is end of sentence
var file_2 = @"F:\Tests\10kk.txt"; //905mb

//Hello from Zenno <a href="https://google.com">Click here</a> this is end of sentence
var file_3 = @"F:\Tests\Result.txt";

//Регулярка для замены
var regex = new Regex(@"<a\ .*?</a>");

var links = File.ReadLines(file_1, Encoding.UTF8).ToList();
var lines = File.ReadLines(file_2, Encoding.UTF8);


var fs = new FileStream(file_3, FileMode.OpenOrCreate, FileAccess.Write);
var sw = new StreamWriter(fs, Encoding.UTF8);
sw.AutoFlush = true;

foreach(string line in lines)
{
    var changedStr = line;
    var mCount = regex.Matches(changedStr).Count;
 
    for(int i=0; i< mCount; i++)
    {
        if(links.Count > 0)
        {
            var link = links.ElementAt(0);
            links.RemoveAt(0);
            changedStr = regex.Replace(changedStr, link, i+1);
        }
    } 
    sw.WriteLine(changedStr);
}

sw.Close();
fs.Close();
Собирай финальный список в 1 и записывай полностью, а то у тебя все время идут накладные нагрузки на отправку драйверу жесткого диска маленьких данных на запись с большим буффером, вот ты и записываешь их медленно. Плюс можно использовать Parallel.Foreach
Также не стоит удалять данные с листа, а легче их записывать в очередь (или защищенную коллекцию очереди при Parallel.Foreach), так как листы работают медленнее коллекций очередей и стеков
 

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)