Blog
C# : Reading and Writing Binary Files into and outo your Database
14 Jun 2008 | 0 Comments | Permalink
If you're storing binary data in your database, such as in an SQL Server "image" field you might find the following two helper functions handy, make them static like this and never fiddle with filestreams again:
using System.IO;
public sealed class IOTools
{
static public int BinaryRead( string FileName , out byte[] BIN )
{
//read the file for storage
FileStream fs = new FileStream( FileName ,
FileMode.OpenOrCreate,
FileAccess.Read);
int ByteCount = System.Convert.ToInt32(fs.Length);
BIN = new byte[Bytes];
fs.Read(BIN, 0, Bytes);
fs.Close();
return ByteCount;
}
static public void BinaryWrite( string FileName , byte[] BIN , int Bytes )
{
//make sure the target dir exists
Directory.CreateDirectory( FileTools.GetDirectoryName( FileName ) );
FileStream fs = new FileStream(FileName,
FileMode.OpenOrCreate,
FileAccess.Write);
fs.Write(BIN, 0, Bytes);
fs.Close();
}
static public string GetDirectoryName( string s )
{
//catch an MS bug: it wil strip the final dirname
//if the input path is not terminated with a slash.
if( Directory.Exists( s ) )
return s;
return Path.GetDirectoryName(s);
}
}
When storing a byte array in SQL Server remember to store the bytecount in an adjacent field, as performing a sizeof operation when saving out from the database won't yield the correct answer and you'll end up with a corrupt file.
Your basic usage when using System.Data would then look something like this:
public void StoreFile( string FileName , DataRow dr )
{
byte[] BIN;
dr[ "ByteCount" ] = IOTools.BinaryRead( FileName , out BIN );
dr[ "ByteArray" ] = BIN;
}
ByteCount and ByteArray are nice column names if you're obsessive-compulsive because they're both the same length... or is that just me? The save-to-disk case is a simple matter of casting:
public void ExtractFile( string FileName , DataRow dr )
{
IOTools.BinaryWrite( FileName ,
(byte[])dr[ "ByteArray" ] ,
(int)dr[ "ByteCount" ] );
}
Though if that usage were frequent you might want to overload BinaryWrite with a ( string , object , object ) signature and fold the casting into there - along with your usual sanity checks.
C# : Reading between the Tags - extracting the HTML contents of a control
02 May 2008 | 0 Comments | Permalink
Because CHAN uses its own take on rendering as well as controls that can insert themselves in the HEAD of a page I needed to be able to extract the HTML present in the ASPX page between the opening and closing tags of a control. The most obvious reason you might want to do this is to get the Text into a custom TEXTAREA based control:
<TEXTAREA>This is a text area with text in.</TEXTAREA>
The CHAN Script and CSS controls perform this exact trick, reading their contents out of the ASPX:
<Chan:Script runat="server" inline="false">
function MyFunc()
{
alert( "Foo" );
}
</Chan:Script>
When the Script Control has inline=false set its contents are inserted into the HEAD of the document, rather than where they are placed on the ASPX page. The CHAN runtime extracts this via a Chan.Controls.Control base function called Tag_Contents():
public string Tag_Contents()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
System.Web.UI.HtmlTextWriter tw = new System.Web.UI.HtmlTextWriter(sw);
base.Render(tw);
return sb.ToString();
}
Basically to get the contents from the control we need to call System.Web.UI.Control.Render and pass it a HtmlTextWriter, this is chained into a StringWriter and a StringBuilder to finally get our string out! Finally, because we are drilling into the built-in Render function any Child controls will be rendered into the output stream - very handy if you want to, for example serve a portion of a page rather than the whole thing for AJAX purposes.
C# : Rebuilding the Querystring
08 Mar 2008 | 0 Comments | Permalink
This is one of those things you find yourself needing to do fairly often, usually it's because you need the full path + querystring in a form action attribute, or maybe you want to pass the querystring to a child-page of a list of search results so you can easily provide a non-javascript back-link.
This function will therefore spit out a complete replica of the querystring for you, including capturing multiple occurrences of the same key, the final encoding is up to you, you'd at least want to HtmlEncode but you can also re UrlEncode it too to pass it onto those child pages if you need to.
One thing this does not provide is removal or substitution of a value, handy if you want a series of search result links each with a different "Page=x" value, for example, that's left as an exersise for the reader :-)
public string RebuildQueryString()
{
int iKey,iVal,KeyCount,ValCount;
string[] asKeys,asVals;
System.Collections.Specialized.NameValueCollection qs =
System.Web.HttpContext.Current.Request.QueryString;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
asKeys = qs.AllKeys;
KeyCount = asKeys.Length;
if( KeyCount > 0 )
{
sb.Append( '?' );
for( iKey = 0 ; iKey < KeyCount ; iKey++ )
{
asVals = qs.GetValues(i);
ValCount = asVals.Length;
for( iVal = 0 ; iVal < ValCount ; iVal++ )
{
if( iKey > 0 || iVal > 0 )
sb.Append( '&' );
sb.Append( asKeys[iKey] );
sb.Append( '=' );
sb.Append( UrlEncode( asVals[iVal] ) );
}
}
}
return sb.ToString();
}