Monday, October 28, 2013

Working with String data in C#

 

In this tutorial we’re going to take a tour of the features offered by string type(System.String),working with them,manipulating them and working with Regular Expressions.The keyword string is similar to System.String,in fact it is just a reference to .NET’s base class System.String.So whether you are using string or System.String ,they mean same.Due to the fact that almost every C# program uses string data somewhere,C# has a simple keyword to represent the base class System.String,which is string.String is just a collection of characters(an array of characters),if you ever had a background in C++ you’d knew how you used the char keyword to declare string data,like

char mystring[ ] = ””;.

Strings are reference types that means they can be set to null,for example :

string csharpstring = null;

and because of being reference types they are stored on the managed heap(A managed heap is similar to heap but it is maintained by Common Language Runtime(CLR) of .NET platform.So that now we know some basics about strings,let’s focus ourselves to other functions of strings.

 

Declaring a string :

A string can be declared like any other type in C#,such as ,

string mystring = “This is a string.”;

using implicitly typed variable,

var mystring = “This is a string.”;

or if you don’t need or don’t know the value,you can leave the string to null,

string mystring = null;

var mystring = null;

or to assign a new string variable or field to a previously declared one,

string previousstring = “This one’s older.”;

string newstring = previousstring;

when you declare a string(or any other) variable or field it simply takes the value of it’s right hand field or variable.So newstring will now hold the string assigned to previousstring.

 

Declaring a string array :

Declaring a string array is very similar to declaring a string.If you know the number of elements any their values at time of declaring,you can use this syntax to declare a string array,

string[ ] mystringarray = {“First String”,”Second String”,”Third String”,”And So on…”};

other way of doing this,

string[ ] mystringarray = new string[ ]{“First String”,”Second String”,”Third String”,”And So on…”};

or if you don’t know the value at time of declaration you can use implicit array declaration,like this,

string[ ] mystring = new string[ ]{ };

using implicitly typed variable,

var mystring = new string[ ]{ };

 

Adding(Concatenating) two or more strings :

To add two or more strings one can make use of + operator.For example :

string first = “CSharp is a ”;

string second = “object oriented ”;

string third = “language".”; 

string sentence= first + second + third;

Can you guess what would be the value of sentence ? It will definitely be CSharp is a object oriented language.This method is useful if you have small strings but is no well suited to add up long strings.For this specific purpose C# has a tailored class StringBuilder.As its name itself says it is useful to build strings.So let’s see how we can put StringBuilder to some good work.To follow along create a new ConsoleApplication project in your preferred IDE,name it “WorkingWithStrings”.If the project is created successfully you’ll see the Program.cs file open in the code editor.Now in the Main  method create an instance of StringBuilder class like this,

StringBuilder stringBuilder = new StringBuilder( );

The constructor has 5 overloads where you can define the following;

  • Capacity of this instance.
  • Maximum capacity of this instance.
  • An initial string with which to initialize this instance.
  • Start index and length of the string from which this instance is to be initialized.

Now that we know how to initialize the class let’s focus on how we can put it to some good work.Okay let’s try create the above sentence with our new tool,to add any string or other value type to a string we make use of Append(—) method.For Example :

stringBuilder.Append(“CSharp is a ”);

stringBuilder.Append(“object oriented ”);

stringBuilder.Append(“language.”);

The above three statements similar to first + second + third in working.Now to get our final string we use ToString(—) method.We can get the final string(sentence) in this way,

string sentence = stringBuilder.ToString();

So the final code looks like this,


using System;

using System.Text;

namespace WorkingWithStrings

{

class Program

{

static void Main(string[] args)

{

// First Method : Using + operator to concatenate strings

string first = "CSharp is a ";

string second = "object oriented ";

string third = "language.";

string sentence = first + second + third;

Console.WriteLine("Using + Operator :");

Console.WriteLine(sentence);

Console.WriteLine();

//

// Second Method : Using StringBuilder class

StringBuilder stringBuilder = new StringBuilder();

stringBuilder.Append("CSharp is a ");

stringBuilder.Append("object oriented ");

stringBuilder.Append("language.");

sentence = stringBuilder.ToString();

Console.WriteLine("Using StringBuilder :");

Console.WriteLine(sentence);

Console.WriteLine();

//

Console.ReadLine();

}

}

}


You can compile the code above directly with no modifications,copy and overwrite your code with this one,build and run the solution.When you run the solution you’ll see there is no difference between outputs of both.

 

Working with file paths :

A path of a file,for example:Notepad,on the disk looks like,

C:\Windows\Notepad.exe

but you cannot declare a path or pattern of this form in C# because C# treats \(Backslash) as an escape character,so you need to escape a backslash with another backslash,so that it looks like,

string path = “C:\\Windows\\Notepad.exe”;

Another way,perhaps more cleaner to do this is using @ symbol.So that it now looks like,

string path = @“C:\Windows\Notepad”;

Both declarations are valid but the second one is suggested.

 

Get a string representation of other types :

The ultimate base class of .NET is System.Object ,all other classes are derived from this one.System.Object has four methods ,

  • Equals(—);
  • GetHashCode(—);
  • GetType(—)
  • ToString(—);

Due to the fact that all derived classes inherit borrow the methods from their parent,every class in C# even those created by you have the above four methods.The fourth one is specially useful because many a times one needs to convert some type to a string.So let’s try to convert some other types to string starting with the most popular one i.e int (System.Int32).To convert an int to a string we can use the ToString(—) method(recall that every class of .NET is derived from System.Object which implements this method and so System.Int32 is no exception),like this,

int number = 2013;

string converted = number.ToString();

After this converted will return 2013 as string.Similarly one can convert a byte,double,float,ulong etc.

But why would someone need to convert something to a string ? The reason is simple,when you need to show some data in a TextBox,RichTextBox or MessageBox,everything goes fine until you’ve string data but may become typical(if you don’t know how to do it)when you’ve some other type of data int,double etc.These controls required that the data to be displayed is of string type and that’s when ToString(—) comes to rescue.To make this more clear try out these examples in a ConsoleApplication project.

// Example 1

Console.WriteLine(DateTime.Now.ToString());// Prints the date and time of the moment this statement gets executed.

// Example 2

double dValue = 10.5;

Console.WriteLine(dValue.ToString());// Prints 10.5

// Example 3

StringBuilder stringBuilder2 = new StringBuilder("A hello from StringBuilder");

Console.WriteLine(stringBuilder2.ToString());

// Example 4

string root = System.IO.Path.GetPathRoot(Environment.SystemDirectory);// Gets the root word of the drive the current OS is installed.

string[] files = System.IO.Directory.GetFiles(root + @"\Windows");// Gets an array of file paths of all files in %Systemroot\Windows.

Console.WriteLine("Total files in " + root + @"\Windows" + " : " + files.Length.ToString());// Prints out total no of files in path declared above.

 

Formatting strings :

Formatting strings is another important task which your application uses if you are really not making an image editor of audio editor.Again,string already has inbuilt functionality for this purpose which is available to us via Format(—) method.The syntax is like this,

string.Format(—);

This method takes two or more input arguments depending upon the number of format items.A format item is represented as {n},where n can be any number.Valid declarations are {0},{100},{95} etc.Format items always start from 0 {0}.A valid declaration of string.Format(—) is,

string.Format(“Your name is {0} and age is {1}.”,”John Doe”,100-75);

When the statement executes every format item in the string gets replaced by its corresponding object.For example : For first format item {0} the first supplied argument is used and so on,so the above statement will output,

Your name is John Doe and age is 25.

Every format item gets replaced by corresponding object

 

Regular Expressions :

A regular expression is sequence of characters and metacharacters in a codified form.Metacharacters can themselves represent a sequence of characters.A regular expression looks something like,

\d+

Regular expressions are invaluable tool for text processing and they can simplify many long tasks such as finding doubled words,matching dates email addresses,user input against some pattern and lots of other things.Regular expressions are so popular and useful that one can consider them as a programming language in themselves.And giving a complete tutorial is out of scope of this post,but if you really want a quick and good start,this is an excellent tutorial.Below is a quick reference of some common patterns,

  • +        One or more.
  • *     Any number of times,greedy matches the maximum available.
  • +?      One or more but as few as possible
  • \d       Matches a single digit(The same applies to \w(whitespace),\s(string))
  • \d+     Matches a sequence of digits but the sequence must have at least one digit(Also applies to \w,\s).
  • [a-z]   Matches a single lowercase alphabet(Same with [A-Z])
  • [a-z]+ Matches sequence of lowercase alphabets but sequence must have at least one alphabet(Same with [A-Z])
  • . (dot) Matches any character except newline in SingleLine mode

Sunday, October 27, 2013

Decompressing files in C#

 

This tutorial is the second part of the tutorial Compressing files in C#.If you’ve not read that one,I suggest you read it.

 

ExtractToDirectory :

In this tutorial we’ll be focusing on Decompressing files in C#.To follow along create a ConsoleApplication project in Visual Studio or you preferred IDE,name it Decompression Test.Here is the code to decompress a compressed archive to a specified folder(PS : The code below can be immediately compiled just like the first part.) :


using System;

using System.IO;

using System.IO.Compression;

namespace Decompression_Test

{

class Program

{

static void Main(string[] args)

{

// A Zip archive to decompress.

string sourceArchive = null;

// A folder to put the extracted files into.

string destinationFolder = null;

// To check if a valid file is selected.

bool IsSelectedFileValid = false;

while (IsSelectedFileValid != true)// Loop until a valid filename is found.

{

Console.WriteLine("Please enter path to a Zip archive...");

Console.WriteLine();

sourceArchive = Console.ReadLine();// Get path entered by user.

if (sourceArchive.Contains("\""))// Strip off inverted commas.

sourceArchive = sourceArchive.Replace("\"", "");

if (!File.Exists(sourceArchive))// If the entered path doesn't exist.

{

Console.WriteLine("The path you entered is invalid.Please try again.");

Console.WriteLine();

}

else// If the entered path exists.

{

IsSelectedFileValid = true;

}

}

// To check if the destination folder is valid.

bool IsSelectedPathValid = false;

while (IsSelectedPathValid != true)// Loop until a valid path is entered.

{

Console.WriteLine("Please enter the destination folder...");

Console.WriteLine();

destinationFolder = Console.ReadLine();// Get the path entered by user.

if (destinationFolder.Contains("\""))// Strip off all inverted commas.

destinationFolder = destinationFolder.Replace("\"", "");

if (!Directory.Exists(destinationFolder))// If the entered path is invalid.

{

Console.WriteLine("The destination folder is invalid.Try again with a valid one.");

Console.WriteLine();

IsSelectedPathValid = false;

}

else// The user entered a valid path.

{

IsSelectedPathValid = true;// Break the loop.

}

}

try

{

// We need to check out if the file is actually a Zip archive or it had been renamed to look like Zip file.

// If an InvalidDataException is thrown,it flags the reality of file,this means whatever the file be,its most probably not

// a Zip archive or is corrupted.

ZipFile.ExtractToDirectory(sourceArchive, destinationFolder);// Extract all files in the archive to destination folder.

Console.WriteLine("Successfully extracted the archive.Press Enter to exit.");

Console.Read();

}

catch (System.IO.InvalidDataException)

{

Console.WriteLine("The archive you selected is either damaged or its another filetype with .zip extension.Press Enter to exit.");

Console.Read();

}

catch (Exception exception)

{

Console.WriteLine(exception.Message + "Press Enter to exit.");

Console.Read();

}

}

}

}



Go on build and run the solution,enter path to a Zip file on disk,press enter,now enter a target folder’s path(use Desktop =>%SystemRoot/Users/UserName/Desktop) and press enter if the file you selected is valid one you’ll see contents on your desktop folder.Now find a mp3,exe,png or any other type of file rename its extension to .zip and try to open this one,when you do that you’ll see the error message written in catch block of InvalidDataException,this means any invalid operations throw this exception.Again here is the project if you need.

Saturday, October 26, 2013

Compressing files in C#

 

C# provides a variety of classes that provide services to deal with compression and decompression of data (and files as well).Most of them provide you with methods to create ZIP archives from files,folders or streams.These classes are defined under the following namespace :

  • System.IO.Compression

To use this namespace in your projects you’ll need to add a reference to “System.IO.Compression.dll” assembly.This namespace provides the following classes suited for compression,decompression and reading of data(and files as well).

  1. DeflateStream : Provides methods and properties for compressing and decompressing streams using the Deflate algorithm.
  2. GzipStream : Provides methods and properties used to compress and decompress streams.
  3. ZipArchive : Represents a package of compressed files in ZIP archive format.
  4. ZipArchiveEntry : Represents a compressed file within a ZIP archive.
  5. ZipFile : Provides static methods for creating,extracting and opening ZIP archives.

So those were the classes offered by .NET and thus C# for compression and decompression.As this tutorial is not going to be a long essay,so I’ll not discuss each class,MSDN already has enough documentation on the topic.So lets start by discussing the class ZipFile.This class,as its name suggests,provides basic services(static methods) to deal with ZIP archives i.e creation and extraction.To get started let’s try to compress some files and folders using this class.ZipFile has two methods to deal with compression and decompression,they are ,

  • CreateFromDirectory : “Creates a zip archive that contains the files and directories from the specified directory.”As the documentation itself says this method allows you to create a Zip archive from the specified folder.It requires a path to a valid folder as first required argument,a destination archive name as second required argument.Other overloads provide a level of compression to be applied and a value specifying whether the base directory should be included or not.
  • ExtractToDirectory : “Extracts all the files in the specified zip archive to a directory on the file system.”This method is almost an inverse of the first one,as first required argument it demands a path to a valid Zip archive and the second argument demands a path to put the extracted files.

 

CreateFromDirectory :

So let’s start by trying out the first method,to follow along create a new ConsoleApplication project in Visual Studio or the IDE of your choice,name it “Compression Test”.Here is the code to create a compressed archive from files(PS : The code below can be immediately compiled,just overwrite the code in your Program.cs file with this one) :


using System;

using System.IO;

using System.IO.Compression;

namespace Compression_Test

{

class Program

{

static void Main(string[] args)

{

#region Input Path routine

// The Input folder to archive.

string inputPath = null;

// The Output folder to put the resulting archive.

string outputPath = null;

// To check if the Input folder is valid one.

bool sourceFolderIsValid = false;

// Loop recursively until a valid folder path is entered.

while (sourceFolderIsValid != true)

{

Console.WriteLine("Please enter path of a folder to archive...");

inputPath = Console.ReadLine();

if (inputPath.Contains("\""))// Strip out inverted commas from the path,if any,as they make the path invalid.

inputPath = inputPath.Replace("\"", "");

if (!Directory.Exists(inputPath))// In each iteration,check if this time a valid path has been entered.

{

Console.WriteLine("The source folder is invalid.Please try again");

Console.WriteLine();

sourceFolderIsValid = false;// Set this to false to keep the loop running.

}

else// A valid path is found,break the loop.

{

sourceFolderIsValid = true;// Set this to true to break the loop.

}

}

#endregion

#region Output Path routine

// To check if the Output folder is valid one.

bool outputFolderIsValid = false;

while (outputFolderIsValid != true)// Loop recursively to check for a valid path.

{

Console.WriteLine("Please enter path to destination archive...");

outputPath = Console.ReadLine();

if (outputPath.Contains("\""))// Strip inverted commas from the path,if any,as they may make the path invalid.

outputPath = outputPath.Replace("\"", "");

if (outputPath.Equals(inputPath))// Check if the destination path is not same as source path.

{

Console.WriteLine("The destination folder cannot be same as source,please try with different one.");

Console.WriteLine();

outputFolderIsValid = false;//Set this to false to keep the loop running.

}

else// Hmm,this time the destination is not same as source,but is it valid ?

{

if (!Directory.Exists(outputPath))// Check if the path is valid.

{

Console.WriteLine("The destination folder is invalid.Please try again");

Console.WriteLine();

outputFolderIsValid = false;//Set this to false to keep the loop running.

}

else

{

outputFolderIsValid = true;// Set this to true to break the loop.

}

}

}

#endregion

#region Compression Routine

Console.WriteLine("Please wait...Compressing files");

Console.WriteLine();

try

{

// Create a temporary path to check for files whose names might conflict with this archive’s name.

string tempOutputPath = string.Format("{0}\\Compressed Archive.zip", outputPath);

if (!File.Exists(tempOutputPath))// Check if the path already exists.

{

ZipFile.CreateFromDirectory(inputPath, tempOutputPath);//No,it doesn’t,we can use this one.

}

else// Damn,the path already exists,we need to create a similar version ourselves.

{

for (int counter = 1; ; counter++)// We're going to use the numbering technique as Explorer uses.

{

tempOutputPath = string.Format("{0}\\Compressed Archive {1}.zip", outputPath, counter);// Create a path with current value of counter.

if (!File.Exists(tempOutputPath))// Check if the new path exists.

{

ZipFile.CreateFromDirectory(inputPath, tempOutputPath);//No,it doesn’t,we’ll use this one.

break;// Break the loop.

}

}

}

Console.WriteLine("The archive has been created successfully.Press Enter to exit.");// Greet the user and say bye.

Console.ReadKey();

}

catch (Exception exception)

{

Console.WriteLine(exception.Message);

Console.WriteLine();

Console.WriteLine("Press enter to exit.");

Console.ReadLine();

}

#endregion

}

}

}


Go on,build and run the project,enter a folder path that has some files in it,press Enter,then enter a target folder(use Desktop=>%SystemRoot/Users/UserName/Desktop for now),press Enter and you’ll see a compressed archive on your Desktop.Here is the project which I’ve compressed using the application we created just now.Missed out anything,please point it out.In the next tutorial we’ll be discussing Decompression.