Introduction
RTools.Util is a small C# library containing some utility classes. The primary classes are:
StreamTokenizer
: A stream tokenizer like Java's which can be useful for parsing text. This takes text (from a file, string, etc) in a stream and produces a list of Token objects. The Token objects are subclassed to provide type information. Some Token subclasses are WordToken
, CharToken
, WhitespaceToken
, QuoteToken
, CommentToken
, FloatToken
, etc.
Opts
: A command-line option parsing class similar to the perl/unix getopts.
Finder
: A small "find" utility class for producing lists of files under a particular directory. I created this to use in zipping up this package.
HighResClock
: A wrapper for Kernel32.dll's high resolution clock API. This allows you time information with resolution greater than DateTime.Now's, which is machine dependent but typically 10 or 15 ms. The effective resolution of HighResClock on a P4 1.4GHz is about 10us.
SoftwarePackage
: This class provides some utility methods to do things list installed software packages, etc. This is Windows-only.
Using the code
I've included an Ndoc-generated .chm file in the source download. It contains a lot more information. The information and samples here are a subset of what's in the .chm.
Here are a couple example uses of StreamTokenizer
which illustrate the basics:
StreamTokenizer tokenizer = new StreamTokenizer();
tokenizer.TextReader = File.OpenText(fileName);
tokenizer.GrabWhitespace = true;
tokenizer.Verbosity = VerbosityLevel.Debug;
Token token;
while (NextToken(out token))
{
if (token == '{')
...
}
This use of StreamTokenizer
shows all-at-once tokenization, which trades off performance (tokenize everything even if you aren't going to use all the tokens, and memory) for ease of programming:
StreamTokenizer tokenizer = new StreamTokenizer();
tokenizer.Settings.ParseNumbers = true;
ArrayList tokens = new ArrayList();
if (!tokenizer.TokenizeString("some string", tokens))
{
}
foreach (Token t in tokens) Console.WriteLine("t = {0}", t);
Here's an example use of Opts:
Opts opts = new Opts();
opts.ParseSpec = "file=s, type:s, v, d");
- or -
opts.UsageSpec = "-file fileName -type [typeName] [-v|-d]";
if (!opts.Parse(args, out errorMessage)) {
if (opts.Options.ContainsKey("v"))
if (!opts.Options.ContainsKey("file")) { error...
Console.WriteLine("-file specified is {0}", opts.Options["file"]);
Finder has a Main() which I use for a simple command-line find. Here's an example use of Finder's other methods:
string dirName = ".";
ArrayList regexps = new ArrayList();
regexps.Add("*.cs");
regexps.Add("*.csproj");
SortedList list = new SortedList();
Finder.FindFiles(dirName, regexps, ref list, false);
Finder.AddParents(list);
foreach(DictionaryEntry entry in list)
{
string s = (string)entry.Key;
Console.WriteLine(s);
}
Points of Interest
There's some chance that the version on www.rseghers.name/codeAndUtils.htm is more up to date.
I had high hopes of keeping StreamTokenizer's
tokenization state machine very clean, but the number (floating point) parse forced me into some complexity. I'd be happy to hear better strategies.
It might be better to use a parser-generator (I see that Mono has one, and there's another article on CodeProject that used it) for parsing. The main advantage of StreamTokenizer
, I believe, is that there's a smaller learning curve to use it.
I haven't included an AssemblyInfo.cs file that doesn't reference my private key (.snk) file. I am not including my private key file, and therefore the project I've included won't build as is. You have to remove the reference to my .snk file from AssemblyInfo.cs to get it to build. Sorry, I don't like the idea of having multiple .csproj and AssemblyInfo.cs files, and haven't found a more elegant solution.
History
- Nov 5 2002 - First CodeProject submission.
- Nov 16 2002 - First CodeProject download.
- Jan 27 2003 - Update.
- Oct 22 2004 - Update library to latest version (see changelog.txt in the download). Update this web page accordingly.