Tuesday, 24 November 2015

Locking and unlocking specific bytes of a file in C#

The following code shows a program that can lock and unlock specific bytes of file in C# using FileStream::Lock and FileStream::Unlock in System.IO. To test out that locking can protect designated bytes of a file, start up multiple instances of the program and try writing to the file after it has been locked. This will protect the file to be modified by other processes, which is handy if you want to ensure data integrity of files your system or application uses and expect to have a given contents and format. FileStream class allows us to work on files on a byte level and do detailed I/O operations on files in .NET.


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestOutFileLocking
{

    class FStreamLock
    {

        static void Main(string[] args)
        {
            var uniEncoding = new UnicodeEncoding();
            string lastRecordText = "The last processed record number was: ";
            int textLength = uniEncoding.GetByteCount(lastRecordText);
            int recordNumber = 13;
            int byteCount = uniEncoding.GetByteCount(recordNumber.ToString());
            string tempString;

            using (var fileStream = new FileStream("Test#@@#.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                //Write the original file data. 
                if (fileStream.Length == 0)
                {
                    tempString = lastRecordText + recordNumber.ToString(); 
                    fileStream.Write(uniEncoding.GetBytes(tempString), 0, uniEncoding.GetByteCount(tempString));
                }

                //Allow the user to choose the operation. 
                char consoleInput = 'R'; 
                byte[] readText = new byte[fileStream.Length];
                while (consoleInput != 'X')
                {
                    Console.Write("\nEnter 'R' to read, 'W' to write, 'L' to " + "lock, 'U' to unlock, anything else to exit: ");

                    if ((tempString = Console.ReadLine()).Length == 0)
                    {
                        break;
                    }
                    consoleInput = char.ToUpper(tempString[0]);

                    switch (consoleInput)
                    {
                        //Read data from the file and 
                        //write it to the console 
                        case 'R':
                            try
                            {
                                fileStream.Seek(0, SeekOrigin.Begin);
                                fileStream.Read(readText, 0, (int) fileStream.Length);
                                tempString = new string(uniEncoding.GetChars(readText, 0, readText.Length));
                                Console.WriteLine(tempString);
                                recordNumber = int.Parse(tempString.Substring(tempString.IndexOf(':') + 2)); 

                            }
                            //Catch the IOException generated if the 
                            //specified part of the file is locked. 
                            catch (IOException e)
                            {
                                Console.WriteLine("{0}: The read " +
                                 "operation could not be performed " +
                                 "because the specified part of the " +
                                 "file is locked.",
                                 e.GetType().Name);
                                
                            }

                            break;

                            //Update the file. 
                        case 'W':

                            try
                            {
                                fileStream.Seek(textLength, SeekOrigin.Begin);
                                fileStream.Read(readText, textLength - 1, byteCount);
                                tempString = new string(uniEncoding.GetChars(readText, textLength - 1, byteCount));
                                recordNumber = int.Parse(tempString) + 1;
                                fileStream.Seek(textLength, SeekOrigin.Begin);
                                fileStream.Write(uniEncoding.GetBytes(recordNumber.ToString()), 0, byteCount);
                                fileStream.Flush(); 
                                Console.WriteLine("Record has een updated.");
                            }
                            catch (IOException e)
                            {
                                Console.WriteLine(
                                    "{0}: The write operation could not " +
                                    "be performed because the specified " +
                                    "part of the file is locked.",
                                    e.GetType().Name);
                            } //try-catch 
                            break;

                            //Lock the specified part of the file. 
                        case 'L':

                            try
                            {
                                fileStream.Lock(textLength - 1, byteCount);
                                Console.WriteLine("The specified part " + "of file has been locked.");
                            }
                            catch (IOException err)
                            {
                                Console.WriteLine("{0}: The specified part of file is" + " already locked.", err.GetType().Name);
                            } //try-catch 
                            break; 

                        case 'U':
                            try
                            {
                                fileStream.Unlock(textLength - 1, byteCount);
                                Console.WriteLine("The specified part of file has been unlocked.");

                            }
                            catch (IOException err)
                            {
                                Console.WriteLine("{0}: The specified part of file is " + "not locked by the current prcess.", err.GetType().Name);
                            }
                            break; 

                        default:
                            consoleInput = 'X';
                            break; 

                    } //switch 

                }

            } //using 



        }

    }

}


No comments:

Post a Comment