home *** CD-ROM | disk | FTP | other *** search
- /*=====================================================================
- File: WordCount.cs
-
- Summary: Demonstrates how to create a WordCount application
- using various COM+ 2.0 library types.
-
- ---------------------------------------------------------------------
- This file is part of the Microsoft COM+ 2.0 SDK Code Samples.
-
- Copyright (C) 2000 Microsoft Corporation. All rights reserved.
-
- This source code is intended only as a supplement to Microsoft
- Development Tools and/or on-line documentation. See these other
- materials for detailed information regarding Microsoft code samples.
-
- THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- PARTICULAR PURPOSE.
- =====================================================================*/
-
- // Add the classes in the following namespaces to our namespace
- using System;
- using System.IO;
- using System.Collections;
-
-
- class WordCountArgParser : ArgParser {
-
- // Members identifying command-line argument settings
- private Boolean showAlphabeticalWordUsage;
- private Boolean showOccurranceWordUsage;
- private String outputFile;
- private ArrayList pathnames = new ArrayList();
-
-
- // Give the set of valid command-line switches to the base class
- public WordCountArgParser() : base(new string[] { "?", "a", "o", "f" }) {
- }
-
-
- // Returns the name of the user-specified output file or null if not specified
- public String OutputFile { get { return outputFile; } }
-
-
- // Indicates whether the user wanted to see all the words sorted alphabetically
- public Boolean ShowAlphabeticalWordUsage {
- get { return showAlphabeticalWordUsage; }
- }
-
-
- // Indicates whether the user wanted to see all the words sorted by occurrance
- public Boolean ShowOccurranceWordUsage {
- get { return showOccurranceWordUsage; }
- }
-
-
- // Shows application's usage info and also reports command-line argument errors.
- public override void OnUsage(String errorInfo) {
- if (errorInfo != null) {
- // An command-line argument error occurred, report it to user
- // errInfo identifies the argument that is in error.
- Console.WriteLine("Command-line switch error: {0}\n", errorInfo);
- }
-
- Console.WriteLine("Usage: WordCount [-a] [-o] [-f<output-pathname>] input-pathname...");
- Console.WriteLine(" -? Show this usage information");
- Console.WriteLine(" -a Word usage sorted alphabetically");
- Console.WriteLine(" -o Word usage sorted by occurrance");
- Console.WriteLine(" -f Send output to specified pathname instead of the console");
- }
-
-
- // Called for each non-switch command-line argument (filespecs)
- protected override SwitchStatus OnNonSwitch(String switchValue) {
- SwitchStatus ss = SwitchStatus.NoError;
- // Add command-line argument to array of pathnames.
- String d = File.GetDirectoryNameFromPath(switchValue);
- Directory dir = new Directory((d.Length == 0) ? "." : d);
- // Convert switchValue to set of pathnames, add each pathname to the pathnames ArrayList.
- foreach (File f in dir.GetFiles(File.GetFileNameFromPath(switchValue))) {
- pathnames.Add(f.FullName);
- }
- return(ss);
- }
-
-
- // Returns an enumerator that includes all the user-desired files.
- public IEnumerator GetPathnameEnumerator() {
- return pathnames.GetEnumerator(0, pathnames.Count);
- }
-
-
- // Called for each switch command-line argument
- protected override SwitchStatus OnSwitch(String switchSymbol, String switchValue) {
- // NOTE: For case-insensitive switches,
- // switchSymbol will contain all lower-case characters
-
- SwitchStatus ss = SwitchStatus.NoError;
- switch (switchSymbol) {
-
- case "?": // User wants to see Usage
- ss = SwitchStatus.ShowUsage;
- break;
-
- case "a": // User wants to see all words sorted alphabetically
- showAlphabeticalWordUsage = true;
- break;
-
- case "o": // User wants to see all words sorted by occurrance
- showOccurranceWordUsage = true;
- break;
-
- case "f": // User wants output redirected to a specified file
- if (switchValue.Length < 1) {
- Console.WriteLine("No output file specified.");
- ss = SwitchStatus.Error;
- } else {
- outputFile = switchValue;
- }
- break;
-
- default:
- Console.WriteLine("Invalid switch: \"" + switchSymbol + "\".\n");
- ss = SwitchStatus.Error;
- break;
- }
- return(ss);
- }
-
-
- // Called when all command-line arguments have been parsed
- protected override SwitchStatus OnDoneParse() {
- SwitchStatus ss = SwitchStatus.NoError;
- // Sort all the pathnames in the list
- if (pathnames.Count == 0) {
- Console.WriteLine("No pathnames specified.");
- ss = SwitchStatus.Error;
- } else {
- pathnames.Sort(0, pathnames.Count, null);
- }
- return(ss);
- }
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
-
-
- // The WordCounter class
- public class WordCounter {
- public WordCounter() { /* No interesting construction */ }
-
- // Each object of this class keeps a running total of the files its processed
- // The following members hold this running information
- Int64 totalLines = 0;
- Int64 totalWords = 0;
- Int64 totalChars = 0;
- Int64 totalBytes = 0;
-
- // The set of all words seen (sorted alphabetically)
- SortedList wordCounter = new SortedList();
-
- // The following methods return the running-total info
- public Int64 TotalLines { get { return totalLines; } }
- public Int64 TotalWords { get { return totalWords; } }
- public Int64 TotalChars { get { return totalChars; } }
- public Int64 TotalBytes { get { return totalBytes; } }
-
- // This method calculates the statistics for a single file.
- // This file's info is returned via the out parameters
- // The running total of all files is maintained in the data members
- public Boolean CountStats(String pathname,
- out Int64 numLines, out Int64 numWords, out Int64 numChars, out Int64 numBytes) {
-
- Boolean Ok = true; // Assume success
- numLines = numWords = numChars = numBytes = 0; // Initialize out params to zero
- try {
- // Attempt to open the input file for read-only access
- FileStream fsIn = new FileStream(pathname, FileMode.Open, FileAccess.Read, FileShare.Read);
- numBytes = fsIn.Length;
- StreamReader sr = new StreamReader(fsIn);
-
- // Process every line in the file
- for (String Line = sr.ReadLine(); Line != null; Line = sr.ReadLine()) {
- numLines++;
- numChars += Line.Length;
- String[] Words = Line.Split(null); // Split the line into words
- numWords += Words.Length;
- for (int Word = 0; Word < Words.Length; Word++) {
- if (Words[Word] != null) {
- if (!wordCounter.ContainsKey(Words[Word])) {
- // If we've never seen this word before, add it to the sorted list with a count of 1
- wordCounter.Add(Words[Word], 1);
- } else {
- // If we have seen this word before, just increment its count
- wordCounter[Words[Word]] = (Int32) wordCounter[Words[Word]] + 1;
- }
- }
- }
- }
- // Explicitly close the StreamReader to properly flush all buffers
- sr.Close(); // This also closes the FileStream (fsIn)
- }
- catch (FileNotFoundException) {
- // The specified input file could not be opened
- Ok = false;
- }
- // Increment the running totals with whatever was discovered about this file
- totalLines += numLines;
- totalWords += numWords;
- totalChars += numChars;
- totalBytes += numBytes;
- return(Ok);
- }
-
- // Returns an enumerator for the words (sorted alphabetically)
- public IDictionaryEnumerator GetWordsAlphabeticallyEnumerator() {
- return (IDictionaryEnumerator) wordCounter.GetEnumerator();
- }
-
-
- // This nested class is only used to sort the words by occurrance
- // An instance of this class is created for each word
- public class WordOccurrance : IComparable {
-
- // Members indicating the number of times this word occurred and the word itself
- private int occurrances;
- private String word;
-
- // Constructor
- public WordOccurrance(int occurrances, String word) {
- this.occurrances = occurrances;
- this.word = word;
- }
-
- // Sorts two WordOccurrance objects by occurrance first, then by word
- public int CompareTo(Object o) {
- // Compare the occurance of the two objects
- int n = occurrances - ((WordOccurrance)o).occurrances;
- if (n == 0) {
- // Both objects have the same ccurrance, sort alphabetically by word
- n = String.Compare(word, ((WordOccurrance)o).word);
- }
- return(n);
- }
-
- // Return the occurrance value of this word
- public int Occurrances { get { return occurrances; } }
-
- // Return this word
- public String Word { get { return word; } }
- }
-
-
- // Returns an enumerator for the words (sorted by occurrance)
- public IDictionaryEnumerator GetWordsByOccurranceEnumerator() {
- // To create a list of words sorted by occurrance, we need another SortedList object
- SortedList sl = new SortedList();
-
- // Now, we'll iterate through the words alphabetically
- IDictionaryEnumerator de = GetWordsAlphabeticallyEnumerator();
- while (de.MoveNext()) {
-
- // For each word, we create a new WordOccurrance object which
- // contains the word and its occurrance value.
- // The WordOccurrance class contains a CompareTo method which knows
- // to sort WordOccurrance objects by occurrance value and then alphabetically by the word itself.
- sl.Add(new WordOccurrance((int)de.Value, (string)de.Key), null);
- }
- // Return an enumerator for the words (sorted by occurrance)
- return (IDictionaryEnumerator) sl.GetEnumerator();
- }
-
- // Returns the number of unique words processed
- public int UniqueWords {
- get { return wordCounter.Count; }
- }
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
-
-
- // This class represents the application itself
- class Application {
- public static int Main(String[] args) {
-
- // Parse the command-line arguments
- WordCountArgParser ap = new WordCountArgParser();
- if (!ap.Parse(args)) {
- // An error occurrend while parsing
- return 1;
- }
-
- // If an output file was specified on the command-line, use it
- FileStream fsOut = null;
- StreamWriter sw = null;
- if (ap.OutputFile != null) {
- fsOut = new FileStream(ap.OutputFile, FileMode.Create, FileAccess.Write, FileShare.None);
- sw = new StreamWriter(fsOut);
-
- // By associating the StreamWriter with the console, the rest of
- // the code can think it's writing to the console but the console
- // object redirects the output to the StreamWriter
- Console.SetOut(sw);
- }
-
- // Create a WordCounter object to keep running statistics
- WordCounter wc = new WordCounter();
-
- // Write the table header
- Console.WriteLine("Lines\tWords\tChars\tBytes\tPathname");
-
- // Iterate over the user-specified files
- IEnumerator e = ap.GetPathnameEnumerator();
- while (e.MoveNext()) {
- Int64 NumLines, NumWords, NumChars, NumBytes;
- // Calculate the words stats for this file
- wc.CountStats((String)e.Current, out NumLines, out NumWords, out NumChars, out NumBytes);
-
- // Display the results
- String[] StrArgs = new String[] {
- NumLines.ToString(),
- NumWords.ToString(),
- NumChars.ToString(),
- NumBytes.ToString(),
- (String) e.Current
- };
- Console.WriteLine(String.Format("{0,5}\t{1,5}\t{2,5}\t{3,5}\t{4,5}", StrArgs));
- }
-
- // Done processing all files, show the totals
- Console.WriteLine("-----\t-----\t-----\t-----\t---------------------");
- Console.WriteLine(String.Format("{0,5}\t{1,5}\t{2,5}\t{3,5}\tTotal in all files",
- new object[] { wc.TotalLines, wc.TotalWords, wc.TotalChars, wc.TotalBytes } ));
-
- // If the user wants to see the word usage alphabetically, show it
- if (ap.ShowAlphabeticalWordUsage) {
- IDictionaryEnumerator de = wc.GetWordsAlphabeticallyEnumerator();
- Console.WriteLine(String.Format("Word usage sorted alphabetically ({0} unique words)", wc.UniqueWords));
- while (de.MoveNext()) {
- Console.WriteLine(String.Format("{0,5}: {1}", de.Value, de.Key));
- }
- }
-
- // If the user wants to see the word usage by occurrance, show it
- if (ap.ShowOccurranceWordUsage) {
- IDictionaryEnumerator de = wc.GetWordsByOccurranceEnumerator();
- Console.WriteLine(String.Format("Word usage sorted by occurrance ({0} unique words)", wc.UniqueWords));
- while (de.MoveNext()) {
- Console.WriteLine(String.Format("{0,5}: {1}",
- ((WordCounter.WordOccurrance)de.Key).Occurrances,
- ((WordCounter.WordOccurrance)de.Key).Word));
- }
- }
-
- // Explicitly close the console to guarantee that the StreamWriter object (sw) is flushed
- Console.Out.Close();
- if (fsOut != null) fsOut.Close();
- return 0;
- }
- }
-
-
- ///////////////////////////////// End of File /////////////////////////////////
-