sankarisiva Ответов: 2

Слияние CSV файлов размером до 50 ГБ


I have to merge two CSV files of 50GB size using .net. Please help me a quick process that took less than 5 mintues


Что я уже пробовал:

static void Main(string[] args)
{

строка sourceFolder = @"D:\SingleBlockDataDump_June.csv";
строка destinationFile = @"\D:\SingleBlockDataDump_July.csv";
строка logFilePath = @"D:\log.txt";
// string[] filePaths = каталог.GetFiles(sourceFolder, "CSV_File_Number?.csv");
FileDest модулю записи StreamWriter = новая модулю записи StreamWriter(файл_назначения, правда);

//int i=1;
//for (i = 0; i < filePaths.Длина; i++)
{
//string file = filePaths[i];

string[] lines = файл.ReadAllLines(sourceFolder); //файл.ReadAllLines(файл);

//if (i > 0)
//{
//lines = lines.Skip(1).ToArray(); // пропустить строку заголовка для всех файлов, кроме первого
линии = линии.Метод toArray();
//}
Сроки начала = Дата и время.Сейчас.TimeOfDay;
string logText = "Started to merge:" + startTime +Environment.NewLine;

(строки по каждому элементу в линии)
{
fileDest.WriteLine(строка);
}
Промежуток времени endTime=Датавремя.Сейчас.TimeOfDay;
logText += "законченное слияние:" + endTime;
//Продолжительность периода = дата и время.Parse(endTime).Вычитание(Дата-Время.Синтаксический анализ(начальное время));
logText += "прошедшее время:";
используя (модулю записи StreamWriter инструкция writetext = новая модулю записи StreamWriter(путь_к_файлам_журнала))
{
writetext.WriteLine(logText);
}
Приставка.Линия чтения();
}

fileDest.Рядом();
}

F-ES Sitecore

Вместо того чтобы делать ReadAllLines, попробуйте обработать файл строка за строкой. Не могу гарантировать, что это окажет большое влияние на производительность, но попробовать стоит.

Чтобы опередить ваш следующий вопрос, google "читает файл строка за строкой c#"

2 Ответов

Рейтинг:
1

Mehdi Gholam

CSV-файлы-это текстовые файлы с описанием заголовка, поэтому, если файловые структуры одинаковы, просто добавьте второй файл к первому файлу, пропустив строку заголовка второго файла (первую строку).


Рейтинг:
0

Jochen Arndt

Не используйте чтение строка за строкой (или даже ReadAllLines) если скорость имеет значение.

Выделите большой массив байтов, который будет использоваться для копирования. Размер должен быть справедлив ниже доступной свободной памяти, чтобы избежать подкачки на диск.

Для каждого файла получите его размер и - за исключением первого - прочтите первую строку, чтобы пропустить ее и получить смещение ко второй строке от длины. Вычтите смещение из размера.

Теперь используйте цикл для блочной обработки:


  • Определите размер блока (минимальный размер буфера и оставшийся размер)
  • Считывание в буфер
  • Запись в выходной файл
  • Уменьшение размера по размеру блока

Тогда существует только одно выделение памяти, а чтение и запись содержимого необработанного файла позволяет избежать проверки конца строки. Требуемое время почти полностью зависит от скорости вашего устройства хранения данных (HDD, SSD).


sankarisiva

Спасибо. Если у вас есть какая-либо ссылка на сайт для этой реализации, пожалуйста, поделитесь ссылкой

Jochen Arndt

У меня нет никаких конкретных ссылок на сайт, потому что все задачи общие и не сложные.

Это просто получение размера файла и двоичное чтение и запись файлов. Единственная проблема может заключаться в смешивании двоичного и текстового чтения, чтобы получить длину строки заголовка.

Это можно решить, открыв файл сначала в текстовом режиме, чтобы получить длину, закройте его и снова откройте в двоичном режиме и используйте функцию Seek (), чтобы пропустить первую строку.

Другой (вероятно, более быстрый) вариант-это чтение символов из файла, открытого уже в двоичном режиме, до тех пор, пока не появится новый символ строки.

Если вам действительно нужен пример кода, Вы можете найти что-то вроде "c# copy binary file", потому что он будет содержать большую часть требуемого кода, кроме пропуска первой строки.