/// <see cref="IIntegerFileInfoCollector.GetIntegerFileInfo(string, int)"/>
        public IntegerFileInfo GetIntegerFileInfo(string filePath, int chunkSize)
        {
            Debug.Assert(filePath != null);
            Debug.Assert(chunkSize > 0);

            IntegerFileInfo fileInfo = new IntegerFileInfo()
            {
                NumOfChunks   = 0,
                NumOfIntegers = 0
            };

            //Open a text reader to the file
            using (StreamReader fileReader = fileIO.CreateFileStreamReader(filePath))
            {
                while (!fileReader.EndOfStream)
                {
                    //Read each line to count the number of lines in the file
                    fileReader.ReadLine();

                    fileInfo.NumOfIntegers++;
                }
            }

            //Now that we have the number of integers, calculate the number of chunks
            fileInfo.NumOfChunks = (int)Math.Ceiling(Decimal.Divide(fileInfo.NumOfIntegers, chunkSize));

            return(fileInfo);
        }
예제 #2
0
        /// <summary>
        /// Sorts the integers found in an input file and writes the sorted integers to an output file
        /// </summary>
        /// <param name="options">The command line options</param>
        private static List <string> SortIntegers(CommandLineOptions options)
        {
            IFileIO fileIO = serviceProvider.GetService <IFileIO>();
            IIntegerFileInfoCollector integerFileInfoCollector = serviceProvider.GetService <IIntegerFileInfoCollector>();

            //Find the output directory where the output file will be written
            string outputDirectory = fileIO.GetDirectoryFromFilePath(options.OutputFilePath);

            //Indicate to the user that we are retrieving information regarding the input file. This can take a long
            //time for very large files.
            DisplayInputFileInfoInProgress();

            //Collect information on the input file
            IntegerFileInfo inputFileInfo = integerFileInfoCollector.GetIntegerFileInfo(options.InputFile, (int)options.ChunkSize);

            //Store the intermediate files so that they can be deleted later on
            List <string> intermediateFilePaths = new List <string>();

            List <string> chunkFiles = CreateChunkFiles(options, inputFileInfo, outputDirectory);

            //Translate the file names to file paths
            var chunkFilePaths = chunkFiles.Select(file => Path.Combine(outputDirectory, file)).ToList();

            intermediateFilePaths.AddRange(chunkFilePaths);

            List <string> mergeIntermediateFilePaths = MergeChunkFiles(chunkFiles, options, inputFileInfo);

            intermediateFilePaths.AddRange(mergeIntermediateFilePaths);

            return(intermediateFilePaths);
        }
예제 #3
0
        /// <summary>
        /// Creates the chunk files
        /// </summary>
        /// <param name="options">The command line options</param>
        /// <param name="inputFileInfo">Information regarding the input file</param>
        /// <param name="outputDirectory">The directory where the chunk files will be written</param>
        /// <returns>The chunk files that were created</returns>
        private static List <string> CreateChunkFiles(CommandLineOptions options, IntegerFileInfo inputFileInfo,
                                                      string outputDirectory)
        {
            DisplayInputFileInfo(inputFileInfo);

            //Create the progress bar for the chunk file creation
            var chunkProgressBar = CreateProgressBar(inputFileInfo.NumOfChunks, ChunkProgressMessage);

            //Create the progress callback that will be passed to the chunk file creation code
            Action <int> updateChunkProgress = (int chunkNum) => UpdateProgressBar(chunkProgressBar, chunkNum);

            //Create the sorted chunk files
            string chunkFileTemplate = string.Format(GenFileTemplate, "1", "{0}");

            List <string> chunkFiles = CreateSortedChunkFiles(options.InputFile, (int)options.ChunkSize,
                                                              outputDirectory, chunkFileTemplate, updateChunkProgress);

            if (chunkFiles.Count > 0)
            {
                OnProgressBarCompleted();
            }


            DisplayChunkFileCreationResults(chunkFiles.Count);

            return(chunkFiles);
        }
예제 #4
0
        /// <summary>
        /// Displays the integer file information for the input file
        /// </summary>
        /// <param name="inputFileInfo">The input file information</param>
        private static void DisplayInputFileInfo(IntegerFileInfo inputFileInfo)
        {
            string integerOutput = "Number of Integers: {0}";
            string chunkOutput   = "Number of Chunks: {0}";

            Console.WriteLine(string.Format(integerOutput, inputFileInfo.NumOfIntegers));
            Console.WriteLine(string.Format(chunkOutput, inputFileInfo.NumOfChunks));
        }
예제 #5
0
        /// <summary>
        /// Merges a set of chunk files into a single output file
        /// </summary>
        /// <param name="chunkFiles">The chunk files to be merged</param>
        /// <param name="options">The command line options</param>
        /// <param name="inputFileInfo">Information regarding the input file</param>
        /// <returns>The intermediate files that were created while merging</returns>
        private static List <string> MergeChunkFiles(List <string> chunkFiles, CommandLineOptions options,
                                                     IntegerFileInfo inputFileInfo)
        {
            List <string> intermediateFilePaths = new List <string>();

            IFileIO          fileIO          = serviceProvider.GetService <IFileIO>();
            IChunkFileMerger chunkFileMerger = serviceProvider.GetService <IChunkFileMerger>();

            //Find the output directory where the output file will be written
            string outputDirectory = fileIO.GetDirectoryFromFilePath(options.OutputFilePath);

            //Convert the chunk file names into chunk file paths
            List <string> chunkFilePaths = chunkFiles
                                           .Select(chunkFileName => Path.Combine(outputDirectory, chunkFileName))
                                           .ToList();

            //Keep a dictionary of progress bars where the key is the merge generation number, and
            //the value is the progress bar for that merge generation
            Dictionary <int, ProgressBar> mergeProgressBars = new Dictionary <int, ProgressBar>();

            Action <int, int> updateMergeProgress = (int gen, int integersProcessed) =>
            {
                if (!mergeProgressBars.ContainsKey(gen))
                {
                    //Create a progress bar for the current generation
                    mergeProgressBars[gen] = CreateProgressBar(inputFileInfo.NumOfIntegers,
                                                               string.Format(MergeProgressMessage, gen - 1));
                }

                bool stepsComplete = UpdateProgressBar(mergeProgressBars[gen], integersProcessed);

                if (stepsComplete)
                {
                    OnProgressBarCompleted();

                    //Display the results of the merge operation. We can calculate the number of output
                    //files that will result from each merge generation
                    int mergedFilesCount = CalculateNumberOfGenerationOutputFiles(chunkFiles.Count, MergeCount,
                                                                                  gen - FirstMergeGeneration + 1);

                    DisplayGenMergeResults(gen, mergedFilesCount);
                }
            };


            List <string> mergeFiles = chunkFileMerger.MergeChunkFilesIntoSingleFile(chunkFilePaths, MergeCount, GenFileTemplate,
                                                                                     Path.GetFileName(options.OutputFilePath), outputDirectory, FirstMergeGeneration, !options.KeepIntermediate,
                                                                                     updateMergeProgress);

            intermediateFilePaths.AddRange(mergeFiles);

            return(intermediateFilePaths);
        }