Удаление повторяющихся строк из очень большого текстового файла

Мне нужно удалить повторяющиеся строки из чрезвычайно большого текстового файла (100 Gb +)

Так как удаление дубликатов памяти является безнадежным из-за размера данных, я попробовал bloomfilter, но не использовал ничего, кроме 50 миллионов строк.

суммарные строки равны 1 триллиону +

Я хочу знать, каковы способы решения этой проблемы.

Моя первоначальная попытка состоит в том, чтобы делить файл на количество подфайлов, отсортировать каждый файл, а затем объединить все файлы вместе...

Если у вас есть лучшее решение, чем это, пожалуйста, дайте мне знать,

Спасибо..

Ответ 1

Ключевой концепцией, которую вы ищете, является внешняя сортировка. Вы должны иметь возможность объединить сортировку всего файла, используя методы, описанные в этой статье, и затем последовательно запускать их для удаления дубликатов.

Если статья недостаточно ясна, посмотрите на упомянутые реализации, такие как этот.

Ответ 2

Вы можете сделать второй файл, который содержит записи, каждая запись - это 64-битный CRC плюс смещение строки, и файл должен быть проиндексирован для быстрого поиска. Что-то вроде этого:

ReadFromSourceAndSort()
{
   offset=0;
   while(!EOF)
   {
      string = ReadFromFile();
      crc64 = crc64(string);
      if(lookUpInCache(crc64))
      {
         skip;
      } else {
         WriteToCacheFile(crc64, offset);
         WriteToOutput(string);
      }
   }
}

Как создать хороший кеш файл? Он должен быть отсортирован по CRC64 для быстрого поиска. Таким образом, вы создаете структуру этого файла как двоичное дерево поиска, но с быстрым добавлением новых элементов, не перемещаясь в файле. Чтобы улучшить скорость, вам нужно использовать "Файлы с памятью" .

Возможный ответ:

memory = ReserveMemory(100 Mb);
mapfile= MapMemoryToFile(memory, "\\temp\\map.tmp"); (File can be bigger, Mapping is just window)
currentWindowNumber = 0;

while(!EndOfFile)
{
  ReadFromSourceAndSort(); But only for first 100 Mb in memory
  currentWindowNumber++;
  MoveMapping(currentWindowNumber)
}

И функция поиска; Shuld не использует сопоставление (потому что каждое переключение окон сохраняет 100 Мб на HDD и загружает 100 МБ следующего окна). Просто ищет в деревьях 100Mb CRC64 и если CRC64 найден → строка уже сохранена