Create A Resource File From File System Directory
We have a collection of files in a nested directory layout that we need to distribute as resources, so I wrote this small class to do it.
The ultimate use of the resource file that is so we can distribute this relatively large collection of small files in a single unit and allow the web application to grab the content via a handler. One could just use Visual Studio but it's editor is too slow when you get a bunch of file based resources.
using System;
using System.Text;
using System.Resources;
using System.IO;
public class ArchiveToResx
{
public void Create(string dir, string resx)
{
m_dir = dir;
m_resf = resx;
m_resx = new ResXResourceWriter(m_resf);
DoDirectory(new DirectoryInfo(c.m_dir));
m_resx.AddResource("lut", (object)c.m_lut.ToString());
m_resx.Generate();
m_resx.Close();
}
// Traverse the directory and for each file create and entry in the resource
// file and increment a counter. Save the counter value and the name in a
// string that will be saved later to act as a look up table.
public void DoDirectory(DirectoryInfo di)
{
foreach (System.IO.FileInfo f in di.GetFiles())
{
using (FileStream fs = f.OpenRead())
{
byte[] contents = new byte[f.Length];
fs.Read(contents, 0, contents.Length);
string key = f.FullName.Replace(m_dir, string.Empty);
key = key.Replace("\\", "/");
if (key.StartsWith("/")) key = key.Substring(1);
m_resx.AddResource("f" + m_cnt.ToString(), contents);
if (m_lut.Length > 0) m_lut.Append(m_sep);
m_lut.Append("f").Append(m_cnt).Append(m_sep).Append(key);
m_cnt++;
}
}
foreach (System.IO.DirectoryInfo d in di.GetDirectories())
{
DoDirectory(d);
}
}
private int m_cnt = 1;
private StringBuilder m_lut = new StringBuilder();
private string m_sep = "|";
private string m_dir;
private string m_resf;
private ResXResourceWriter m_resx;
public static void Main()
{
MyClass c = new MyClass();
c.Create(@"C:\temp\directory", @"C:\temp\directory.resx");
}
}
After the resx file is created, I just drop it into Visual Studio. Here's an IHttpHandler that shows how the resource file is expanded and used.
using System;
using System.Collections.Generic;
using System.Web;
public class MyPathHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string[] lut = MyResources.lut.Split('|');
Dictionary dict = new Dictionary();
for (int i = 0; i < lut.Length; i += 2)
{
dict.Add(lut[i + 1], lut[i]);
}
// Strip the part of the path that we use to get this handler called.
string physicalPath = context.Request.Path.Replace("/Path/", string.Empty);
if (dict.ContainsKey(physicalPath))
{
byte[] body = GetFile(dict[physicalPath]);
context.Response.BinaryWrite(body);
context.Response.Flush();
return;
}
context.Response.WriteFile(context.Server.MapPath(context.Request.Path));
}
public bool IsReusable
{
get
{
return true;
}
}
private byte[] GetFile(string id)
{
return (byte[])MyResources.ResourceManager.GetObject(id,
MyResources.Culture);
}
}
There are no comments.