Thanks Ian,

You got it correct, it's the IO cost and time constraint that I am worried
about. The log file is generated on a daily basis, still the amount of data
that is written to the log file is moderately large.

I want the logging process to complete as fast as possible because when
multiple transactions are submitted simultaneously, one transaction should
not take a longer period to make other transactions slow. The amount of data
that is written to the log file is moderately large per transaction.

Also, for the logging purpose I have built a wrapper class which holds all
the string data (using StringBuilder) that needs to be written for the
transaction and the final write is performed only once at the end of the
transaction so that the file is not blocked.

Here's the class...


using System;
using System.IO;
using System.Text;

/// <summary>
/// This class safely writes data to the file and also handles the write
/// operation efficiently by using lock. Lock is required when two or
/// more users write data to the same file simultaneously
/// </summary>
public class SafeFileLogger
{
       private const int DATA_SIZE = 1000;  // Needs to be finalized

       private static object m_Synchronize = new object();                      
       // used for locking
       private string m_strFilePath = string.Empty;                             
       // file path to which data
is written
       private StringBuilder m_objSB = null;                                    
               // String Builder used for
writing bufferd data to the file
       private bool m_boolIsDataBuffered = false;                               
               // indicates whether or not
the data is buffered
       private int m_intBufferSize;                                             
                       // buffer size, used for setting the
capacity for the StringBuilder object
       private LogDirection m_LogDirection = LogDirection.Beginning;


       /// <summary>
       /// The default constructor
       /// </summary>
       public SafeFileLogger()
       {
       }


       /// <summary>
       /// This constructor of this class accepts the file path as a parameter
       /// </summary>
       /// <param name="strFilePath">The file path to which data needs to be
written</param>
       public SafeFileLogger(string strFilePath)
       {
               this.m_strFilePath = strFilePath;
       }


       public static string GetLogFilePath()
       {
               // Write code for getting the file path specific to the project
//              string folderName =
System.Configuration.ConfigurationSettings.AppSettings["AirLogFolder"].ToString();
//              string fileName = folderName + "Air-{" + DateTime.Now.Year + 
"-" +
DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + "}.txt";
//              return fileName;
               return @"D:\c.txt";
       }


       /// <summary>
       /// Indicates whether the output is buffered before it is written to the
file
       /// </summary>
       public bool Buffered
       {
               get{ return this.m_boolIsDataBuffered; }
               set{ this.m_boolIsDataBuffered = value; }
       }


       /// <summary>
       /// Indicates the size of the buffer
       /// </summary>
       public int BufferSize
       {
               get{ return this.m_intBufferSize; }
               set
               {
                       try
                       {
                               this.m_intBufferSize = value;
                               this.m_objSB.Capacity = value;
                       }
                       catch
                       {
                               throw;
                       }
               }
       }


       public LogDirection Direction
       {
               get{ return this.m_LogDirection; }
               set{ this.m_LogDirection = value; }
       }

       /// <summary>
       /// This method safely writes data to the file ensuring
       /// multiple users are able to write simultaneously
       /// </summary>
       /// <param name="strData">The data to be written to the file</param>
       public void Write( string strData )
       {
               if ( m_boolIsDataBuffered )
               {
                       if (this.m_objSB == null) this.m_objSB = new
StringBuilder(SafeFileLogger.DATA_SIZE);

                       this.m_objSB.Append( strData );
                       return;
               }
               else
               {
                       this.SafeWrite( strData );
               }
       }


       /// <summary>
       /// This method appends the line terminating character to the data
       /// that is to be written
       /// </summary>
       /// <param name="strData"></param>
       public void WriteLine( string strData )
       {
               this.Write( strData + "\r\n");
       }


       /// <summary>
       /// This is the main private method which actually does the work
       /// of writing it to the file
       /// </summary>
       /// <param name="strData"></param>
       private void SafeWrite( string strData )
       {
               FileStream fs = null;

               // Check if the file name to which the data needs to
               // be written is set
               //--------------------------------------------------
               if ( this.m_strFilePath == string.Empty )
               {
                       this.m_strFilePath = SafeFileLogger.GetLogFilePath();
               }
               lock(m_Synchronize)
               {
                       try
                       {
                               // Check if the file exists otherwise create a 
new file
                               
//------------------------------------------------------------
                               if ( !File.Exists( m_strFilePath ))
                               {
                                       (File.CreateText( m_strFilePath 
)).Close();
                               }


                               // Now decide the write direction
                               
//------------------------------------------------------------
                               if ( this.m_LogDirection == 
LogDirection.Beginning )
                               {

                                       // Firstly read the existing file and 
take the contents
                                       // into a byte array
                                       
//------------------------------------------------------------
                                       fs = new FileStream(m_strFilePath, 
FileMode.Open, FileAccess.Read);
                                       byte[] arrOriginalText = new 
byte[fs.Length];
                                       fs.Read(arrOriginalText, 0, 
arrOriginalText.Length);
                                       fs.Close(); fs = null;
                                       
//------------------------------------------------------------


                                       // Now write the data to the file by 
re-creating the new file
                                       
//------------------------------------------------------------
                                       fs = new FileStream(m_strFilePath, 
FileMode.Create, FileAccess.Write);


                                       // Convert the new data to be written to 
a byte array
                                       
//------------------------------------------------------------
                                       byte[] arrNewText = new byte[ 
strData.Length ];
                                       Encoding.UTF8.GetBytes( strData, 0, 
strData.Length, arrNewText, 0 );


                                       // Now write data - first the new text 
and then the original
                                       
//------------------------------------------------------------
                                       fs.Write(arrNewText, 0, 
arrNewText.Length);
                                       fs.Write(arrOriginalText, 0, 
arrOriginalText.Length);

                                       
//------------------------------------------------------------



                               }
                               else
                               {

                                       fs = new FileStream(m_strFilePath, 
FileMode.Append, FileAccess.Write);

                                       byte[] arrNewText = new byte[ 
strData.Length ];
                                       Encoding.UTF8.GetBytes( strData, 0, 
strData.Length, arrNewText, 0 );

                                       fs.Write(arrNewText, 0, 
arrNewText.Length);
                               }
                       }
                       catch
                       {
                               throw;
                       }
                       finally
                       {
                               // Close the stream
                               
//------------------------------------------------------------
                               if (fs != null)
                               {
                                       fs.Flush();
                                       fs.Close();
                                       fs = null;
                               }
                       }
               }
       }

       /// <summary>
       /// This method directs the buffered data to the file and
       /// then clears the existing buffer
       /// </summary>
       public void Flush()
       {
               if ( this.m_boolIsDataBuffered )
               {
                       this.SafeWrite( this.m_objSB.ToString() );
                       this.m_objSB = null;
               }
       }
}

public enum LogDirection
{
       Beginning = 0, End = 1
}


Thanks

Regards,
Girish Jain


From: Ian Griffiths <[EMAIL PROTECTED]>
Reply-To: "Discussion of advanced .NET topics."
<[email protected]>
To: [email protected]
Subject: Re: [ADVANCED-DOTNET] Writing data to the beginning of a file
Date: Fri, 18 Nov 2005 17:02:40 -0000

But didn't he start off by saying he wanted something better than
writing out the entire file again every time he did an insertion?

Moving to XML doesn't solve that file writing problem.

You can insert stuff into an XML DOM, but the DOM is a data structure in
memory. If you want the file on disk to contain the new entry, then you
have to re-serialize the DOM.

So you're getting the DOM to read the whole file in for you and write
the whole thing back out again. Just because the DOM's doing this work
for you doesn't change the fact that the work is still happening.

If all you care about is how much development work is required, then
your solution is fine.  But if the problem you're trying to solve is the
amount of disk activity required, then XML is likely to make things
worse as it's probably going to be more verbose.

So I guess now would be a good time for us to clarify the requirements.
:)

Could the original poster please tell us: is it the IO costs you're
worried about, or the coding effort?


--
Ian Griffiths

-----Original Message-----
From: Jon Rothlander

Based on his questions, he is not using a windows event log and he seems
to
just be using his own log file design.  Nothing in his post says that he
does or does not have control over the format of the log file.  If so,
he
may be able to use XML.  If that is the case, which we cannot really
tell
unless he lets us know, he could use an XML file to hold the entries.
Using
XML allows for much easier access than a text based log file.  In XML
you
can specify the location that you want to add a new node or element to.
For example...

<LogFile>
    <Entry Timestamp="2005-12-25-06:01:59:0000" Type="" Text="This is a
sample entry" />
</LogFile>

With XML you can insert an element anywhere you want.  I can insert them
before of after the last entry, before the first entry, or I can select
one
and insert the record before or after it.

My point was that if he designed his own log file format, he can do
whatever
he wishes and could use XML for this.  Of course, he may not be able to
use
XML if he is not controlling the log file format, which is why I asked
the
question.

I personally use XML for this sort of log file all of the time.  It's
easy
to build viewers via in windows or web that can have a lot of
functionality.

-----Original Message-----
From: Steve Johnson

On 11/18/05, Jon Rothlander <[EMAIL PROTECTED]> wrote:
>
> Can you use XML? If so, you can easily handle this using an XML log
file.
>


How?

===================================
This list is hosted by DevelopMentorĀ®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

===================================
This list is hosted by DevelopMentorĀ®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to