private async Task SplitFileAsync(string inputFileName, int chars) { var sortFiles = new Dictionary <string, StreamData>(AppConstants.Comparer); using (StreamData inputStream = _fileProvider.OpenFileForReading(inputFileName, AppConstants.TextEncoding)) { string line; while ((line = await _fileProvider.ReadNextLineAsync(inputStream)) != null) { if (line.Length < chars) { if (!_noSortParts.TryGetValue(line, out StreamData noSortStream)) { string partFileName = GetNextNoSortPartFileName(); noSortStream = _fileProvider.OpenFileForReadingAndWriting(partFileName, AppConstants.TextEncoding, true); _noSortParts.Add(line, noSortStream); Logger.LogInformation($"Create no sort file {partFileName}"); } await _fileProvider.WriteLineInFileAsync(line, noSortStream); } else { string start = line.Substring(0, chars); if (!sortFiles.TryGetValue(start, out StreamData sortFilePart)) { string partFileName = GetNextPartFileName(); sortFilePart = _fileProvider.OpenFileForReadingAndWriting(partFileName, AppConstants.TextEncoding, true); sortFiles.Add(start, sortFilePart); Logger.LogInformation($"Create sort file {partFileName}"); } await _fileProvider.WriteLineInFileAsync(line, sortFilePart); } } } foreach (var file in sortFiles) { string fileName = file.Value.FileStreamData.Name; long fileSize = file.Value.FileStreamData.Length; await _fileProvider.FlushStreamWriterAsync(file.Value); file.Value.Dispose(); if (fileSize > AppConstants.MaxFilePartSize) { Logger.LogInformation($"Split part file {fileName}"); await SplitFileAsync(fileName, chars + 1); await _fileProvider.DeleteFileIfExistsAsync(fileName); } else { Logger.LogInformation($"Sort part file {fileName}"); await SortFileEntriesAsync(fileName, fileName); if (!_sortParts.TryGetValue(file.Key, out StreamData fileStream)) { fileStream = _fileProvider.OpenFileForReadingAndWriting(fileName, AppConstants.TextEncoding); _sortParts.Add(file.Key, fileStream); } else { _sortParts[file.Key] = _fileProvider.OpenFileForReadingAndWriting(fileName, AppConstants.TextEncoding); } } } }