myfavoritemovies.us

June 22, 2008

Handling Resources in C#

Filed under: C# 3.0 — @ 12:41 am

Most of the people use resources when they want localize a product. Some other uses would be to use static reference files etc., For a month or two I have been use ResourceManager for one of my project. The requirement is very simple, I need to create a resource with bunch of files and then later build the same resource file into a C# project which when running would extract the files from the resource which was build in the previous step. Like any other simple C# coder, I approached the problem with our ResourceReader and ResourceWriter.

I first created a class called Writer as shown below, 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Resources;
using System.IO;
 
namespace ResourceBuilder
{
    public class Writer
    {
        public void WriteFile(string resourceName, string fileName)
        {
            ResourceWriter writer = new ResourceWriter(resourceName);
            CreateFile(fileName);
            byte[] file = File.ReadAllBytes(fileName);
            writer.AddResource(fileName, file);
            writer.Generate();
            writer.Close();
        }
 
        private void CreateFile(string name)
        {
            using (StreamWriter wr = new StreamWriter(name))
            {
                for (int i = 0; i < 5; i++)
                    wr.WriteLine(i.ToString());
            }
        }
    }
}

 
Writer class has one method called WriteFile, which creates a simple resource file and then populate the resource with one text file. The text file is created dynamically.
 
Next I created a class called Reader which does nothing but read the information from the resource file and creates output file. There are two ways you can read the resource file and I created two separate methods to extract in both ways as shown below.
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Resources;
using System.IO;
using System.Reflection;
using System.Collections;
 
namespace ResourceBuilder
{
    public class Reader
    {
        public string ReadFiles(string resourceName, string fileName)
        {
            string outFile = "file1.txt";
            ResourceReader reader = new ResourceReader(resourceName);
            string resourceType;
            byte[] resourceData;
            reader.GetResourceData(fileName, out resourceType, out resourceData);
            File.WriteAllBytes(outFile, resourceData);
            return outFile;
        }
 
        public string ReadWithDictionary(string resourceName, string fileName)
        {
            string outFile = "file2.txt";
            string name;
            object value;
            ResourceReader myReader = new ResourceReader(resourceName);
            IDictionaryEnumerator readerWalker = myReader.GetEnumerator();
            while (readerWalker.MoveNext())
            {
                name = (string)(readerWalker.Key);
                if (name.Equals(fileName))
                {
                    value = readerWalker.Value;
                    File.WriteAllBytes(outFile, (byte[])value);
                    return outFile;
                }
            }
            return "";
        }
    }
}

The first read method ReadFile is the straight opposite of write method. This basically opens the resource file in resource reader mode and fetches the file we are interested in and write it out to a file.

The second method is little different. This still opens the resource file in resource reader mode and then instead of fetching object directory, cast it to IDictionaryEnumurator so that we can traverse the resource file to find out what are all the objects the current resource file has. So if you get a resource file and you would like to find out all the resources in the file, all you have to do is implement the second method, whola, now you can traverse the resource file and get the object by dictionary look up.

Now lets look at the main code which uses the reader and writer together to put all together.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
namespace ResourceBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            Program pg = new Program();
            pg.CreateAndCompareResources();            
        }
 
        private void CreateAndCompareResources()
        {
            string resourceName = "temp.resource";
            string fileName = "file.txt";
            Writer wr = new Writer();
            wr.WriteFile(resourceName, fileName);
            Reader rd = new Reader();
            string outfile = rd.ReadFiles(resourceName, fileName);
            string outfile1 = rd.ReadWithDictionary(resourceName, fileName);
 
            string[] infilea = File.ReadAllLines(fileName);
            string[] outfilea = File.ReadAllLines(outfile);
            string[] outfile1a = File.ReadAllLines(outfile1);
            
            Console.WriteLine("First Match using ResourceReader/Writer is {0}", CompareArrays(infilea, outfilea));
            Console.WriteLine("First Match using ResourceReader/Writer is {0}", CompareArrays(infilea, outfile1a));
            Console.ReadKey();
        }
 
        private bool CompareArrays(string[] infile, string[] outfile)
        {
            if (infile.Length == outfile.Length)
            {
                for (int i = 0; i < infile.Length; i++)
                {
                    if (!infile[i].Equals(outfile[i]))
                        return false;
                }
                return true;
            }
            return false;
        }
    }
}

Now lets go through the program and see what are we trying to do;

1. We create Writer and request it to create a resource file called "temp.resource" and create a file called "file.txt" with following content

0

1

2

3

4

in it and then insert this file into the resource file.

2. We Create a reader class and then we call the first reader method to extract the "file.txt" from "temp.resource" and write the extracted content into a file called "file1.txt".

3. Then we call the same reader class but use the second extract method to extract the "file.txt" from "temp.resource" and write the extracted content into a file called "file2.txt".

4. Next we compare "file.txt" against "file1.txt" and write the match result.

5. Compare "file.txt" against "file2.txt" and write the match result.

Based on the documentation, (4) and (5) should return true.

Now if we run this program the result show be something like the following

image

To our surprise the first match returned false, if you would debug the code and see the content in the "file1.txt", the first four bytes are the size of the file and the "file2.txt" does not have the size of the file in it. That is the difference.  So beware of this difference.

I will research more on this to see why the first method put the size of the file in the beginning. If you know the answer, please post it here or send me a note at ksunair at yahoo.com

I developed the code on XP SP3 using Visual Studio 2008 Express for C# 3.0.

Thanks and happy coding…

Powered by WordPress