Input/Output

Console (Standard I/O)

Since I expect you will have extensive experience working with standard input/output in your previous computer programming courses, it would be useful to highlight the subtle differences C# handles console I/O. For example, in C++, you might have done something like this:

cin >> myChar; // to read a single character from standard input
getline(cin, myString); // to store all characters up until the carriage return, into a string


In Java, you would have had to do a little more legwork...

Scanner sc = new Scanner(System.in);
String myString = sc.next(); // to read a single "token"
String wholeLine = sc.readline(); // to read a whole line


(Declaring a Scanner object before using it?! Java can be exhausting sometimes...) C# will handle standard input more like how Java does.

ConsoleKeyInfo ReadKey() // reads a single character
ConsoleKeyInfo ReadKey(bool Show) // same thing but if Show is true, the key is not displayed
string ReadLine() // functionally identical to "getline" or "readline" from C++/Java, respectively


The ConsoleKeyInfo return types above are structures, which describe each key press, including the combination of keys and locks. If you just want the character, you would do Console.ReadKey().KeyChar.

Output will, again, look more familiar to Java (or C programmers) than it does to C++. There's a Write version that sends the argument to standard output without a newline character at end, and WriteLine that will include a newline character at the end. You can format output in two different ways (the first will look familiar to Java programmers, the second will look familiar to C programmers):

System.Console.WriteLine("My name is " + myName + " and I am pretty great!");
System.Console.WriteLine("Your name is {0} and you are pretty great, too!", yourName);


Where you would increment the value inside the curly braces to refer to any number of variables you can list after the "string format" has been defined.

One thing that C# fumbles with is reading non-string types from input streams. While the >> operator in C++ will implicitly typecast the input based on the data type of the right operand (i.e. cin >> myInt; will attempt to read an integer, if myInt is defined as an integer... which we would all well and hope it is, with a name like that!) or how there's many versions of the next method of Scanner in the Java language, C# has to use an intermediate Convert static class of methods in order to typecast the string-based input as something else. For example, to read a number, you would do:

int myInt = Convert.ToInt32(Console.ReadLine());

But could also do:

int myOtherInt = Int32.Parse(Console.ReadLine());

to achieve the same objective of reading a single number from standard input.

The observant reader may have noticed how we're using ReadLine above, which can be problematic if I, say, write out two numbers separated by a space before hitting the enter key. To compensate for this (again, where I feel like C# fumbled), you could do something like this:

string[] tokens = Console.ReadLine().Split();
for (int i = 0; i < tokens.Length; i++)
myArray[i] = Convert.ToInt32(tokens[i]);


Compensating for non-integer input here is just as problematic as compensating for non-integer input from other languages, though. Generally speaking, if you can't assume something regular about the type of input you're receiving or the order those data types will appear, you're going to have a bad time.

Something neat you can do with standard output in C# is modify the color/style of the output generated. For example, you can change the background/text color produced by doing something like:

System.Console.BackgroundColor = ConsoleColor.White;
System.Console.ForegroundColor = ConsoleColor.Red;
System.Console.WriteLine("This text will be in red, on a white background.");


You can then restore the default color scheme by using System.Console.ResetColor().


File I/O

File input/output will function similar as with C++ and Java, although the syntax used will be slightly different. Because everyone needs their own shtick. Let's consider one example where I'd like to read the contents of an input file, and simply write them out to standard output.

namespace Testing
{
public class TestClass
{
public static void Main()
{
string slacker;
using (StreamReader inFile = new StreamReader("input.txt"))
{
slacker = inFile.ReadLine(); // remember to "prime the read"
while (slacker != null)
{
System.Console.WriteLine(slacker);
slacker = inFile.ReadLine();
}
}
}
}
}


The using statement above acts as a sort of open/close function we might otherwise have had to call before/after the loop. Once we've sequentially reached inside of the bold curly braces highlighted above, inFile will be "open". Once we've gone past the closing curly brace of that pair, inFile will be "closed". Which I think is pretty convenient!

On the flip side, let's look at how I might write everything I type at the keyboard, into an output file.

namespace Testing // Yes, I did cut 'n paste this
{
public class TestClass
{
public static void Main()
{
string slacker = "slacker";
using (StreamWriter outFile = new StreamWriter("output.txt"))
{
while (slacker.CompareTo("q") != 0) // slacker != "q"
{
System.Console.Write("Type in 'q' in order to exit. ");
slacker = System.Console.ReadLine();
outFile.WriteLine(slacker);
}
}
}
}
}


The two above examples don't address the possibility of something going wrong with opening/using/closing these file streams, though, which would certainly be something you'd want to have included in your functional programs. Things like:

if (File.Exists("input.txt")) // "Does this file even exist before I try to use it?"
// File is a static class, so there's no need to declare it anywhere

FileAttributes stats = File.GetAttributes("output.txt");
if ( (stats & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
System.Console.WriteLine("I can't write to a readonly file!");
else
System.Console.WriteLine("All ready to begin writing!");