home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples.exe / WordCount / WordCount.cs < prev   
Encoding:
Text File  |  2000-06-23  |  14.5 KB  |  367 lines

  1. /*=====================================================================
  2.   File:      WordCount.cs
  3.  
  4.   Summary:   Demonstrates how to create a WordCount application
  5.              using various COM+ 2.0 library types.
  6.  
  7. ---------------------------------------------------------------------
  8.   This file is part of the Microsoft COM+ 2.0 SDK Code Samples.
  9.  
  10.   Copyright (C) 2000 Microsoft Corporation.  All rights reserved.
  11.  
  12. This source code is intended only as a supplement to Microsoft
  13. Development Tools and/or on-line documentation.  See these other
  14. materials for detailed information regarding Microsoft code samples.
  15.  
  16. THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  17. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  18. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  19. PARTICULAR PURPOSE.
  20. =====================================================================*/
  21.  
  22. // Add the classes in the following namespaces to our namespace
  23. using System;
  24. using System.IO;
  25. using System.Collections;
  26.  
  27.  
  28. class WordCountArgParser : ArgParser {
  29.  
  30.     // Members identifying command-line argument settings
  31.     private Boolean showAlphabeticalWordUsage;
  32.     private Boolean showOccurranceWordUsage;
  33.     private String  outputFile;
  34.     private ArrayList pathnames = new ArrayList();
  35.  
  36.  
  37.     // Give the set of valid command-line switches to the base class
  38.     public WordCountArgParser() : base(new string[] { "?", "a", "o", "f" }) { 
  39.     }
  40.  
  41.  
  42.     // Returns the name of the user-specified output file or null if not specified
  43.     public String OutputFile { get { return outputFile; } }
  44.  
  45.  
  46.     // Indicates whether the user wanted to see all the words sorted alphabetically
  47.     public Boolean ShowAlphabeticalWordUsage {
  48.         get { return showAlphabeticalWordUsage; }
  49.     }
  50.  
  51.  
  52.     // Indicates whether the user wanted to see all the words sorted by occurrance
  53.     public Boolean ShowOccurranceWordUsage {
  54.         get { return showOccurranceWordUsage; }
  55.     }
  56.  
  57.  
  58.     // Shows application's usage info and also reports command-line argument errors.
  59.     public override void OnUsage(String errorInfo) {
  60.         if (errorInfo != null) {
  61.             // An command-line argument error occurred, report it to user
  62.             // errInfo identifies the argument that is in error.
  63.             Console.WriteLine("Command-line switch error: {0}\n", errorInfo);
  64.         }
  65.  
  66.         Console.WriteLine("Usage: WordCount [-a] [-o] [-f<output-pathname>] input-pathname...");
  67.         Console.WriteLine("   -?  Show this usage information");
  68.         Console.WriteLine("   -a  Word usage sorted alphabetically");
  69.         Console.WriteLine("   -o  Word usage sorted by occurrance");
  70.         Console.WriteLine("   -f  Send output to specified pathname instead of the console");
  71.     }
  72.  
  73.  
  74.     // Called for each non-switch command-line argument (filespecs)
  75.     protected override SwitchStatus OnNonSwitch(String switchValue) {
  76.         SwitchStatus ss = SwitchStatus.NoError;
  77.         // Add command-line argument to array of pathnames.
  78.         String d = File.GetDirectoryNameFromPath(switchValue);
  79.         Directory dir = new Directory((d.Length == 0) ? "." : d);
  80.         // Convert switchValue to set of pathnames, add each pathname to the pathnames ArrayList.
  81.         foreach (File f in dir.GetFiles(File.GetFileNameFromPath(switchValue))) {
  82.             pathnames.Add(f.FullName);
  83.         }
  84.         return(ss);
  85.     }
  86.  
  87.  
  88.     // Returns an enumerator that includes all the user-desired files.
  89.     public IEnumerator GetPathnameEnumerator() {
  90.         return pathnames.GetEnumerator(0, pathnames.Count);
  91.     }
  92.  
  93.  
  94.     // Called for each switch command-line argument
  95.     protected override SwitchStatus OnSwitch(String switchSymbol, String switchValue) {
  96.         // NOTE: For case-insensitive switches, 
  97.         //       switchSymbol will contain all lower-case characters
  98.  
  99.         SwitchStatus ss = SwitchStatus.NoError;
  100.         switch (switchSymbol) {  
  101.  
  102.         case "?":   // User wants to see Usage
  103.             ss = SwitchStatus.ShowUsage; 
  104.             break;
  105.  
  106.         case "a":   // User wants to see all words sorted alphabetically
  107.             showAlphabeticalWordUsage = true;
  108.             break;
  109.  
  110.         case "o":   // User wants to see all words sorted by occurrance
  111.             showOccurranceWordUsage = true;
  112.             break;
  113.  
  114.         case "f":   // User wants output redirected to a specified file
  115.             if (switchValue.Length < 1) {
  116.                 Console.WriteLine("No output file specified.");
  117.                 ss = SwitchStatus.Error; 
  118.             } else {
  119.                 outputFile = switchValue;
  120.             }
  121.             break;
  122.  
  123.         default:
  124.             Console.WriteLine("Invalid switch: \"" + switchSymbol + "\".\n");
  125.             ss = SwitchStatus.Error; 
  126.             break;
  127.         }
  128.         return(ss);
  129.     }
  130.  
  131.  
  132.     // Called when all command-line arguments have been parsed
  133.     protected override SwitchStatus OnDoneParse() {
  134.         SwitchStatus ss = SwitchStatus.NoError;
  135.         // Sort all the pathnames in the list
  136.         if (pathnames.Count == 0) {
  137.             Console.WriteLine("No pathnames specified.");
  138.             ss = SwitchStatus.Error;
  139.         } else {
  140.             pathnames.Sort(0, pathnames.Count, null);
  141.         }
  142.         return(ss);
  143.     }
  144. }
  145.  
  146.  
  147. ///////////////////////////////////////////////////////////////////////////////
  148.  
  149.  
  150. // The WordCounter class
  151. public class WordCounter {
  152.     public WordCounter() { /* No interesting construction */ }
  153.  
  154.     // Each object of this class keeps a running total of the files its processed
  155.     // The following members hold this running information
  156.     Int64 totalLines = 0; 
  157.     Int64 totalWords = 0;
  158.     Int64 totalChars = 0;
  159.     Int64 totalBytes = 0;
  160.  
  161.     // The set of all words seen (sorted alphabetically)
  162.     SortedList wordCounter = new SortedList();
  163.  
  164.     // The following methods return the running-total info
  165.     public Int64 TotalLines { get { return totalLines; } }
  166.     public Int64 TotalWords { get { return totalWords; } }
  167.     public Int64 TotalChars { get { return totalChars; } }
  168.     public Int64 TotalBytes { get { return totalBytes; } }
  169.  
  170.     // This method calculates the statistics for a single file.
  171.     // This file's info is returned via the out parameters
  172.     // The running total of all files is maintained in the data members
  173.     public Boolean CountStats(String pathname, 
  174.         out Int64 numLines, out Int64 numWords, out Int64 numChars, out Int64 numBytes) {
  175.  
  176.         Boolean Ok = true;  // Assume success
  177.         numLines = numWords = numChars = numBytes = 0;  // Initialize out params to zero
  178.         try {
  179.             // Attempt to open the input file for read-only access
  180.             FileStream fsIn = new FileStream(pathname, FileMode.Open, FileAccess.Read, FileShare.Read);
  181.             numBytes = fsIn.Length;
  182.             StreamReader sr = new StreamReader(fsIn);
  183.  
  184.             // Process every line in the file
  185.             for (String Line = sr.ReadLine(); Line != null; Line = sr.ReadLine()) {
  186.                 numLines++;
  187.                 numChars += Line.Length;
  188.                 String[] Words = Line.Split(null);  // Split the line into words
  189.                 numWords += Words.Length;
  190.                 for (int Word = 0; Word < Words.Length; Word++) {
  191.                     if (Words[Word] != null) {
  192.                         if (!wordCounter.ContainsKey(Words[Word])) {
  193.                             // If we've never seen this word before, add it to the sorted list with a count of 1
  194.                             wordCounter.Add(Words[Word], 1);
  195.                         } else {
  196.                             // If we have seen this word before, just increment its count
  197.                             wordCounter[Words[Word]] = (Int32) wordCounter[Words[Word]] + 1;
  198.                         }
  199.                     }
  200.                 }
  201.             }
  202.             // Explicitly close the StreamReader to properly flush all buffers
  203.             sr.Close(); // This also closes the FileStream (fsIn)
  204.         }
  205.         catch (FileNotFoundException) {
  206.             // The specified input file could not be opened
  207.             Ok = false;
  208.         }
  209.         // Increment the running totals with whatever was discovered about this file
  210.         totalLines += numLines;
  211.         totalWords += numWords;
  212.         totalChars += numChars;
  213.         totalBytes += numBytes;
  214.         return(Ok);
  215.     }
  216.  
  217.     // Returns an enumerator for the words (sorted alphabetically)
  218.     public IDictionaryEnumerator GetWordsAlphabeticallyEnumerator() {
  219.         return (IDictionaryEnumerator) wordCounter.GetEnumerator();
  220.     }
  221.  
  222.  
  223.     // This nested class is only used to sort the words by occurrance
  224.     // An instance of this class is created for each word
  225.     public class WordOccurrance : IComparable {
  226.  
  227.         // Members indicating the number of times this word occurred and the word itself
  228.         private int occurrances;
  229.         private String word;
  230.  
  231.         // Constructor
  232.         public WordOccurrance(int occurrances, String word) {
  233.             this.occurrances = occurrances;
  234.             this.word = word;
  235.         }
  236.  
  237.         // Sorts two WordOccurrance objects by occurrance first, then by word
  238.         public int CompareTo(Object o) {
  239.             // Compare the occurance of the two objects
  240.             int n = occurrances - ((WordOccurrance)o).occurrances;
  241.             if (n == 0) {
  242.                 // Both objects have the same ccurrance, sort alphabetically by word
  243.                 n = String.Compare(word, ((WordOccurrance)o).word);
  244.             }
  245.             return(n);
  246.         }
  247.  
  248.         // Return the occurrance value of this word
  249.         public int Occurrances { get { return occurrances; } }
  250.  
  251.         // Return this word
  252.         public String Word { get { return word; } }
  253.     }
  254.  
  255.  
  256.     // Returns an enumerator for the words (sorted by occurrance)
  257.     public IDictionaryEnumerator GetWordsByOccurranceEnumerator() {
  258.         // To create a list of words sorted by occurrance, we need another SortedList object
  259.         SortedList sl = new SortedList();
  260.  
  261.         // Now, we'll iterate through the words alphabetically
  262.         IDictionaryEnumerator de = GetWordsAlphabeticallyEnumerator();
  263.         while (de.MoveNext()) {
  264.  
  265.             // For each word, we create a new WordOccurrance object which
  266.             // contains the word and its occurrance value.
  267.             // The WordOccurrance class contains a CompareTo method which knows
  268.             // to sort WordOccurrance objects by occurrance value and then alphabetically by the word itself.
  269.             sl.Add(new WordOccurrance((int)de.Value, (string)de.Key), null);
  270.         }
  271.         // Return an enumerator for the words (sorted by occurrance)
  272.         return (IDictionaryEnumerator) sl.GetEnumerator();        
  273.     }
  274.  
  275.     // Returns the number of unique words processed
  276.     public int UniqueWords {
  277.         get { return wordCounter.Count; }
  278.     }
  279. }
  280.  
  281.  
  282. ///////////////////////////////////////////////////////////////////////////////
  283.  
  284.  
  285. // This class represents the application itself
  286. class Application {
  287.     public static int Main(String[] args) {
  288.  
  289.         // Parse the command-line arguments
  290.         WordCountArgParser ap = new WordCountArgParser();
  291.         if (!ap.Parse(args)) {
  292.             // An error occurrend while parsing
  293.             return 1;
  294.         }
  295.  
  296.         // If an output file was specified on the command-line, use it
  297.         FileStream fsOut = null;
  298.         StreamWriter sw = null;
  299.         if (ap.OutputFile != null) {
  300.             fsOut = new FileStream(ap.OutputFile, FileMode.Create, FileAccess.Write, FileShare.None);
  301.             sw = new StreamWriter(fsOut);
  302.  
  303.             // By associating the StreamWriter with the console, the rest of 
  304.             // the code can think it's writing to the console but the console 
  305.             // object redirects the output to the StreamWriter
  306.             Console.SetOut(sw);
  307.         }
  308.  
  309.         // Create a WordCounter object to keep running statistics
  310.         WordCounter wc = new WordCounter();
  311.  
  312.         // Write the table header
  313.         Console.WriteLine("Lines\tWords\tChars\tBytes\tPathname");
  314.  
  315.         // Iterate over the user-specified files
  316.         IEnumerator e = ap.GetPathnameEnumerator();
  317.         while (e.MoveNext()) {
  318.             Int64 NumLines, NumWords, NumChars, NumBytes;
  319.             // Calculate the words stats for this file
  320.             wc.CountStats((String)e.Current, out NumLines, out NumWords, out NumChars, out NumBytes);
  321.  
  322.             // Display the results
  323.             String[] StrArgs = new String[] { 
  324.                 NumLines.ToString(), 
  325.                 NumWords.ToString(), 
  326.                 NumChars.ToString(), 
  327.                 NumBytes.ToString(), 
  328.                 (String) e.Current 
  329.             };
  330.             Console.WriteLine(String.Format("{0,5}\t{1,5}\t{2,5}\t{3,5}\t{4,5}", StrArgs));
  331.         }
  332.  
  333.         // Done processing all files, show the totals
  334.         Console.WriteLine("-----\t-----\t-----\t-----\t---------------------");
  335.         Console.WriteLine(String.Format("{0,5}\t{1,5}\t{2,5}\t{3,5}\tTotal in all files", 
  336.             new object[] { wc.TotalLines, wc.TotalWords, wc.TotalChars, wc.TotalBytes } ));
  337.  
  338.         // If the user wants to see the word usage alphabetically, show it
  339.         if (ap.ShowAlphabeticalWordUsage) {
  340.             IDictionaryEnumerator de = wc.GetWordsAlphabeticallyEnumerator();
  341.             Console.WriteLine(String.Format("Word usage sorted alphabetically ({0} unique words)", wc.UniqueWords));
  342.             while (de.MoveNext()) {
  343.                 Console.WriteLine(String.Format("{0,5}: {1}", de.Value, de.Key));
  344.             }
  345.         }
  346.  
  347.         // If the user wants to see the word usage by occurrance, show it
  348.         if (ap.ShowOccurranceWordUsage) {
  349.             IDictionaryEnumerator de = wc.GetWordsByOccurranceEnumerator();
  350.             Console.WriteLine(String.Format("Word usage sorted by occurrance ({0} unique words)", wc.UniqueWords));
  351.             while (de.MoveNext()) {
  352.                 Console.WriteLine(String.Format("{0,5}: {1}", 
  353.                     ((WordCounter.WordOccurrance)de.Key).Occurrances, 
  354.                     ((WordCounter.WordOccurrance)de.Key).Word));
  355.             }
  356.         }
  357.  
  358.         // Explicitly close the console to guarantee that the StreamWriter object (sw) is flushed
  359.         Console.Out.Close();         
  360.         if (fsOut != null) fsOut.Close();
  361.         return 0;
  362.     } 
  363. }
  364.  
  365.  
  366. ///////////////////////////////// End of File /////////////////////////////////
  367.