diff --git a/Task3/Task3/Program.cs b/Task3/Task3/Program.cs
index e839438..d421133 100644
--- a/Task3/Task3/Program.cs
+++ b/Task3/Task3/Program.cs
@@ -1,13 +1,36 @@
using Task3;
+using Mono.Options;
-if (args.Length > 0)
+string? path = null;
+int memoryLimit = WordCounter.DEFAULT_MEMORY_LIMIT;
+bool doParallel = false, showHelp = false;
+var options = new OptionSet()
+{
+ { "f|file=", "the {FILE} to use as input", v => path = v },
+ { "m|memory=", "the max amount of {MEMORY} used while reading data", v =>
+ {
+ bool success = int.TryParse(v, out int memory);
+ if (success) memoryLimit = memory;
+ }
+ },
+ { "p", "count words using multiple threads", v => doParallel = v != null },
+ { "h", "show help", v => showHelp = v != null }
+};
+options.Parse(args);
+
+if (showHelp)
+{
+ ShowHelp(options);
+ return;
+}
+
+WordCounter wordCounter = new WordCounter(memoryLimit);
+long result = 0;
+if (path != null)
{
- string path = args[0];
- bool doParallel = args.Length > 1 && args[1] == "-p";
try
{
- WordCounter wordCounter = new WordCounter(path);
- wordCounter.ProcessText(doParallel: doParallel);
+ result = wordCounter.ProcessFileInput(path, doParallel: doParallel);
}
catch (FileNotFoundException ex)
{
@@ -18,9 +41,14 @@ if (args.Length > 0)
Console.WriteLine(ex.Message);
}
}
-else
-{
- WordCounter wordCounter = new WordCounter();
- wordCounter.ProcessTextConsole();
-}
+else result = wordCounter.ProcessConsoleInput(doParallel: doParallel);
+Console.WriteLine(result);
+static void ShowHelp(OptionSet options)
+{
+ Console.WriteLine("Usage: ./Task3.exe [OPTIONS]+ message");
+ Console.WriteLine("Counts amount of words in the specified input.");
+ Console.WriteLine();
+ Console.WriteLine("Options:");
+ options.WriteOptionDescriptions(Console.Out);
+}
diff --git a/Task3/Task3/Task3.csproj b/Task3/Task3/Task3.csproj
index 9ad2a07..8a31a9e 100644
--- a/Task3/Task3/Task3.csproj
+++ b/Task3/Task3/Task3.csproj
@@ -7,4 +7,7 @@
enable
+
+
+
diff --git a/Task3/Task3/Task3.csproj.bak b/Task3/Task3/Task3.csproj.bak
new file mode 100644
index 0000000..6e29ffb
--- /dev/null
+++ b/Task3/Task3/Task3.csproj.bak
@@ -0,0 +1,11 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
+
diff --git a/Task3/Task3/WordCounter.cs b/Task3/Task3/WordCounter.cs
index 48c34d6..13e131d 100644
--- a/Task3/Task3/WordCounter.cs
+++ b/Task3/Task3/WordCounter.cs
@@ -8,18 +8,13 @@ namespace Task3
{
public class WordCounter
{
- protected const int DEFAULT_MEMORY_LIMIT = 1_048_576; // 1 Mb
+ public const int DEFAULT_MEMORY_LIMIT = 1_048_576; // 1 Mb
///
/// Memory limit for reading data in bytes, set to 1_048_576 bytes
///
public int MemoryLimit { get; set; }
- ///
- /// StreamReader for line by line data input, used by the TextProcessor to read data
- ///
- public StreamReader? Input { get; set; }
-
///
/// StreamWriter for line by line data output, used by the TextProcessor to write data
///
@@ -33,10 +28,10 @@ namespace Task3
///
/// Creates an instance of WordCounter with the specified memory limit for reading data, input and output streams
///
+ /// StreamWriter outputting the result
/// Memory limit for reading data in bytes, set to 1_048_576 by default
- public WordCounter(StreamReader input, StreamWriter output, int memoryLimit = DEFAULT_MEMORY_LIMIT)
+ public WordCounter(StreamWriter output, int memoryLimit = DEFAULT_MEMORY_LIMIT)
{
- Input = input;
Output = output;
MemoryLimit = memoryLimit;
}
@@ -44,51 +39,8 @@ namespace Task3
///
/// Creates an instance of WordCounter with the specified memory limit for reading data and an input stream. Sets console as an output
///
- /// StreamWriter supplying data to the WordCounter
/// Memory limit for reading data in bytes, set to 1_048_576 by default
- public WordCounter(StreamReader input, int memoryLimit = DEFAULT_MEMORY_LIMIT)
- {
- Input = input;
- Output = new StreamWriter(Console.OpenStandardOutput());
- MemoryLimit = memoryLimit;
- }
-
- ///
- /// Creates an instance of WordCounter with the specified memory limit for reading data, an input and an output from specified files
- ///
- /// Name of the file used for input
- /// Name of the file used for output
- /// Memory limit for reading data in bytes, set to 1_048_576 by default
- public WordCounter(string inputFile, string outputFile, int memoryLimit = DEFAULT_MEMORY_LIMIT)
- {
- SetFileInput(inputFile);
- SetFileOutput(outputFile);
- MemoryLimit = memoryLimit;
- }
-
- ///
- /// Creates an instance of WordCounter with the specified memory limit for reading data and an input from specified file. Sets console as an output
- ///
- /// Name of the file used for input
- /// Memory limit for reading data in bytes, set to 1_048_576 by default
- public WordCounter(string inputFile, int memoryLimit = DEFAULT_MEMORY_LIMIT)
- {
- SetFileInput(inputFile);
- Output = new StreamWriter(Console.OpenStandardOutput());
- MemoryLimit = memoryLimit;
- }
-
- ///
- /// Creates an instance of WordCounter with the specified memory limit for reading data.
- /// Input is set to null, should be specified somewhere later in code before calling the processing methods.
- /// Sets console as an output
- ///
- /// Memory limit for reading data in bytes, set to 1_048_576 by default
- public WordCounter(int memoryLimit = DEFAULT_MEMORY_LIMIT)
- {
- Output = new StreamWriter(Console.OpenStandardOutput());
- MemoryLimit = memoryLimit;
- }
+ public WordCounter(int memoryLimit = DEFAULT_MEMORY_LIMIT) : this(new StreamWriter(Console.OpenStandardOutput()), memoryLimit) { }
// simple write to output line by line
protected void WriteData(string result)
@@ -151,29 +103,59 @@ namespace Task3
/// If true, writes the result to specified Output, true by default
/// If true, processes data in parallel by partitioning the blocks of data. Recommended to use with a memory limit of at least 100 Kb, true by default
/// The result of data processing
- public long ProcessText(bool doWrite = true, bool doParallel = true)
+ public long ProcessText(StreamReader input, bool doWrite = true, bool doParallel = true)
{
- if (Input == null) throw new ArgumentNullException("No input was found");
Func countingFunc = doParallel ? CountWordsParallel : CountWordsNonParallel; // determine the processing function to use (no if statememnt on every read)
char prevChar = ' ';
char[] currentBlock = new char[MemoryLimit]; // init buffer for the data
- int charsRead = Input.ReadBlock(currentBlock, 0, MemoryLimit); // first read
+ int charsRead = input.ReadBlock(currentBlock, 0, MemoryLimit); // first read
long wordsAmount = 0;
// while there are chars being read, continue reading
while (charsRead > 0)
{
wordsAmount += countingFunc(currentBlock, prevChar, charsRead); // process data
prevChar = currentBlock[^1]; // set the prev char to the last char of the current block
- charsRead = Input.ReadBlock(currentBlock, 0, MemoryLimit); // read data
+ charsRead = input.ReadBlock(currentBlock, 0, MemoryLimit); // read data
}
string result = wordsAmount.ToString();
if (doWrite) WriteData(result); // write data to output if needed
// release resources
- Input.Dispose();
- Output.Dispose();
+ input.Dispose();
return wordsAmount;
}
+ ///
+ /// Starts the WordCounter. Reads and processes data, then writes (if doWrite is true) and returns it
+ ///
+ /// A string to process
+ /// If true, writes the result to specified Output, true by default
+ /// If true, processes data in parallel by partitioning the blocks of data. Recommended to use with a memory limit of at least 100 Kb, true by default
+ ///
+ public long ProcessString(string data, bool doWrite = false, bool doParallel = false)
+ {
+ long wordsAmount;
+ if (doParallel) wordsAmount = CountWordsParallel(data.ToCharArray(), ' ', data.Length);
+ else wordsAmount = CountWordsNonParallel(data.ToCharArray(), ' ', data.Length);
+ string result = wordsAmount.ToString();
+ if (doWrite) WriteData(result); // write data to output if needed
+ // release resources
+ return wordsAmount;
+ }
+
+ ///
+ /// Starts the WordCounter using file as input. Reads and processes data, then writes (if doWrite is true) and returns it
+ ///
+ /// Name of the file used for input
+ /// If the file doesn't exist
+ /// If the specified file is a directory
+ public long ProcessFileInput(string filePath, bool doWrite = true, bool doParallel = true)
+ {
+ FileInfo fileInfo = FindFile(filePath);
+ FileStream fileStream = fileInfo.OpenRead();
+ StreamReader fileReader = new StreamReader(fileStream, TextEncoding);
+ return ProcessText(fileReader, doWrite, doParallel);
+ }
+
private static FileInfo FindFile(string filePath)
{
FileInfo fileInfo = new FileInfo(filePath);
@@ -183,15 +165,27 @@ namespace Task3
}
///
- /// Sets a file as a WordCounter input
+ /// Starts the WordCounter using console as input. Reads and processes data, then writes (if doWrite is true) and returns it
///
- /// Name of the file used for input
- public void SetFileInput(string filePath)
+ /// If true, writes the result to specified Output, true by default
+ /// If true, processes data in parallel by partitioning the blocks of data. Recommended to use with a memory limit of at least 100 Kb, false by default
+ /// The result of data processing
+ public long ProcessConsoleInput(bool doWrite = true, bool doParallel = false)
{
- FileInfo fileInfo = FindFile(filePath);
- FileStream fileStream = fileInfo.OpenRead();
- StreamReader reader = new StreamReader(fileStream, TextEncoding);
- Input = reader;
+ Console.WriteLine($"Подсчёт слов в тексте, нажмите Ctrl-Z для окончания ввода");
+ string? line;
+ MemoryStream stream = new MemoryStream();
+ StreamWriter sw = new StreamWriter(stream);
+ while (true)
+ {
+ line = Console.ReadLine();
+ if (line == null || line.Contains('\u001A')) break;
+ sw.WriteLine(line);
+ }
+ sw.Flush();
+ stream.Position = 0;
+ StreamReader console = new StreamReader(stream);
+ return ProcessText(console, doWrite, doParallel);
}
///
@@ -206,57 +200,6 @@ namespace Task3
Output = writer;
}
- ///
- /// Starts the WordCounter using console as input. Reads and processes data, then writes (if doWrite is true) and returns it
- ///
- /// If true, writes the result to specified Output, true by default
- /// If true, processes data in parallel by partitioning the blocks of data. Recommended to use with a memory limit of at least 100 Kb, false by default
- /// The result of data processing
- public long ProcessTextConsole(bool doWrite = true, bool doParallel = false)
- {
- Console.WriteLine($"Подсчёт слов в тексте, нажмите Ctrl-Z для окончания ввода");
- string? line;
- MemoryStream stream = new MemoryStream();
- StreamWriter sw = new StreamWriter(stream);
- while (true)
- {
- line = Console.ReadLine();
- if (line == null || line.Contains('\u001A')) break;
- sw.WriteLine(line);
- }
- sw.Flush();
- stream.Position = 0;
- Input = new StreamReader(stream);
- return ProcessText(doWrite, doParallel);
- }
-
- ///
- /// Starts the WordCounter using string value as input. Reads and processes data, then writes (if doWrite is true) and returns it
- ///
- /// If true, writes the result to specified Output, true by default
- /// If true, writes the result to specified Output, false by default
- /// If true, processes data in parallel by partitioning the blocks of data. Recommended to use with a memory limit of at least 100 Kb, false by default
- /// The result of data processing
- public long ProcessString(string data, bool doWrite = false, bool doParallel = false)
- {
- SetStringInput(data);
- return ProcessText(doWrite, doParallel);
- }
-
- ///
- /// Sets a string value as a WordCounter input
- ///
- /// A string value
- public void SetStringInput(string data)
- {
- MemoryStream stream = new MemoryStream();
- StreamWriter sw = new StreamWriter(stream);
- sw.Write(data);
- sw.Flush();
- stream.Position = 0;
- Input = new StreamReader(stream);
- }
-
///
/// Sets console as WordCounter output
///