Thursday, 12 December 2019

C#.NET - Reflection - Get Enum Description from Enum Value

/// Gets the description of the Enumeration provided.
public string GetEnumDescription(Enum value) { return value .GetType() .GetMember(value.ToString()) .FirstOrDefault() .GetCustomAttribute() ?.Description; }

C#.NET - Reflection - Get Enum Value from Description Attribute

Below snippet will get the Enum value by the Enum description
public T GetEnumValueFromDescription(string description)
{
    Type type = typeof(T);
    if (!type.IsEnum)
    {
        throw new ArgumentException();
    }

    FieldInfo[] fields = type.GetFields();
    var field = fields
                    .SelectMany(f => f.GetCustomAttributes(
                        typeof(DescriptionAttribute), false), (
                            f, a) => new { Field = f, Att = a })
                    .Where(a => ((DescriptionAttribute)a.Att)
                        .Description == description).SingleOrDefault();
    return field == null ? default(T) : (T)field.Field.GetRawConstantValue();
}

C#.NET - Large Files Search Processing with Boyer-Moore Searching Algorithm

The below class searches the given string in the specified file. This algorithm is implemented with Boyer-Moore. 

All you need to copy the below full class and call it as shown below.

long searchCount = FileGrep.GetMatchIndexes(filePath, "Hyderabad").Count;

This program can process huge files in seconds.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;

namespace FileProcessor
{
    public class FileGrep
    {
        #region Public Methods
        /// 
        /// Return all matches of the pattern in specified file using the Boyer-Moore algorithm
        /// 
        /// The file to be searched
        /// The size of the buffer to use when reading the file
        /// IEnumerable which returns the indexes of pattern matches
        public static ReadOnlyCollection GetMatchIndexes(string filePath, string searchFor, int bufferSize = 1024 * 1024)
        {
            List matchIndexes = new List();

            if (string.IsNullOrEmpty(searchFor))
            {
                return new ReadOnlyCollection(matchIndexes);
            }

            FileInfo fileToSearch = new FileInfo(filePath);
            if (!fileToSearch.Exists)
            {
                throw new FileNotFoundException();
            }

            if (bufferSize  (Int32.MaxValue - (searchPattern.Length - 1)))
            {
                throw new ArgumentOutOfRangeException("bufferSize", bufferSize, string.Format("Size of the file buffer ({0}) plus the size of the search pattern minus one ({1}) may not exceed Int32.MaxValue ({2}).", bufferSize, (searchPattern.Length - 1), Int32.MaxValue));
            }

            using (FileStream stream = fileToSearch.OpenRead())
            {
                // Make sure that the file stream is seekable to access the data
                if (!stream.CanSeek)
                {
                    throw new Exception(String.Format("The file '{0}' is not seekable!  Search cannot be performed.", fileToSearch));
                }

                int chunkIndex = 0;
                while (true)
                {
                    byte[] fileData = GetNextChunkForSearch(stream, chunkIndex, bufferSize, searchPattern.Length);

                    if (fileData == null || !fileData.Any())
                    {
                        //EOF, so exit
                        break;
                    }

                    List occuranceIndexes = GetMatchIndexes_Internal(fileData, searchPattern, goodSuffixShift, badCharacterShift);

                    if (occuranceIndexes != null)
                    {
                        // We found one or more matches in our buffer.  Translate the buffer index
                        // back to the file index by adding the buffer size * the chunk index.
                        int bufferOffset = (bufferSize * chunkIndex);
                        matchIndexes.AddRange(occuranceIndexes.Select(bufferMatchIndex => (bufferMatchIndex + bufferOffset)));
                    }
                    chunkIndex++;
                } // end while
            }
            return new ReadOnlyCollection(matchIndexes);
        }

        #endregion Public Methods

        #region Helpers
        /// 
        /// Build the bad byte shift array.
        /// 
        /// Pattern for search
        /// Bad byte shift array
        private static long[] BuildBadCharacterShift(byte[] pattern)
        {
            long[] badCharacterShift = new long[256];
            long patternLength = Convert.ToInt64(pattern.Length);

            for (long c = 0; c 
        /// Find suffixes in the pattern
        /// 
        /// Pattern for search
        /// Suffix array
        private static long[] FindSuffixes(byte[] pattern)
        {
            long f = 0;

            long patternLength = Convert.ToInt64(pattern.Length);
            long[] suffixes = new long[pattern.Length + 1];

            suffixes[patternLength - 1] = patternLength;
            long g = patternLength - 1;
            for (long i = patternLength - 2; i >= 0; --i)
            {
                if (i > g && suffixes[i + patternLength - 1 - f] = 0 && (pattern[g] == pattern[g + patternLength - 1 - f]))
                    {
                        --g;
                    }
                    suffixes[i] = f - g;
                }
            }

            return suffixes;
        }
        /// 
        /// Build the good suffix array.
        /// 
        /// Pattern for search
        /// Suffixes in the pattern
        /// Good suffix shift array
        private static long[] BuildGoodSuffixShift(byte[] pattern, long[] suff)
        {
            long patternLength = Convert.ToInt64(pattern.Length);
            long[] goodSuffixShift = new long[pattern.Length + 1];

            for (long i = 0; i = -1; --i)
            {
                if (i == -1 || suff[i] == i + 1)
                {
                    for (; j 
        /// Gets the next chunk of bytes from the stream to perform the search.
        /// 
        /// The stream containing the file to search
        /// The index of the chunk to read from the file
        /// The size of the data chunk to read from the file
        /// The bytes read out of the stream
        private static byte[] GetNextChunkForSearch(Stream stream, int chunkIndex, int fileSearchBufferSize, int searchPatternLength)
        {
            byte[] chunk = null;

            long fileStartIndex = Convert.ToInt64(chunkIndex) * Convert.ToInt64(fileSearchBufferSize);
            if (fileStartIndex = searchPatternLength)
                {
                    // If we read less than the buffer length (end of file), then return a trimmed byte array.
                    if (numBytesRead 
        /// Return all matches of the pattern in specified data using the Boyer-Moore algorithm
        /// 
        /// The data to be searched
        /// List which returns the indexes of pattern matches
        private static List GetMatchIndexes_Internal(byte[] dataToSearch, byte[] searchPattern, long[] goodSuffixShift, long[] badCharacterShift)
        {
            List matchIndexes = new List();

            long patternLength = Convert.ToInt64(searchPattern.Length);
            long textLength = Convert.ToInt64(dataToSearch.Length);

            /* Searching */
            long index = 0;
            while (index = 0)
                {
                    if (searchPattern[unmatched] != dataToSearch[unmatched + index])
                    {
                        //pattern mismatch
                        index += Math.Max(goodSuffixShift[unmatched], badCharacterShift[dataToSearch[unmatched + index]] - patternLength + 1 + unmatched);
                        break;
                    }
                    unmatched--;
                }

                if (unmatched < 0)
                {
                    //match found
                    matchIndexes.Add(index);
                    index += goodSuffixShift[0];
                }
            }

            return matchIndexes;
        }
        #endregion Helpers
    }

}

C#.NET - Convert DateTime from Different TimeZones to UTC

/// Takes the date time and the Zone Name of the DateTime and convert to UTC
public static DateTime ConvertSpecifiedZoneDateTimeToUTC(DateTime dateTime, string timeZoneName)
{
  return TimeZoneInfo.ConvertTimeToUtc(dateTime, TimeZoneInfo.FindSystemTimeZoneById(timeZoneName));
}
// How to Use?
DateTime utcDate= ConvertSpecifiedZoneDateTimeToUTC(DateTime.Now, "Central Standard Time")

C# - How to Convert UTC DateTime to Specific Time Zone

/// Converts UTC DateTime to Given Time Zone
public static DateTime ConvertUtcByZone(DateTime utcDateTime, string destinationTimeZoneName)
        {
            utcDateTime = DateTime.SpecifyKind(utcDateTime, DateTimeKind.Unspecified);
            TimeZoneInfo centralZone = TimeZoneInfo.FindSystemTimeZoneById(destinationTimeZoneName);
            return TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, centralZone);
        }

/// How to use?
ConvertUtcByZone(DateTime.UtcNow, "Central Standard Time")

C# - How to get CST to UTC DateTimeOffset?

DateTimeOffset - Gives detailed date and time difference.
/// <summary>
/// Gets the datetime offset difference between the CST to UTC
/// </summary>
/// <returns></returns>
public static DateTimeOffset GetCstToUtcOffset()
{
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTimeOffset utcOffset = new DateTimeOffset(DateTime.UtcNow, TimeSpan.Zero);
    return utcOffset.ToOffset(cstZone.GetUtcOffset(utcOffset));
}

C# - Read AppSettings / Configuration Settings from File

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
/// <summary>
/// Reads the app settings kyes information for the provided keys
/// </summary>
/// <param name="filePath"></param>
/// <param name="keysToRead"></param>
/// <returns></returns>
private Dictionary<string, string> ReadAppSettings(string filePath, IEnumerable<string> keysToRead)
{
    JObject appsettingsInfo = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(filePath));
        return appsettingsInfo.Root.Values().
                        Select(item => new { Key = item.Path, Value = item.Value<string>() }).
                        Where(item => keysToRead.Contains(item.Key, StringComparer.InvariantCultureIgnoreCase)).
                        Select(item => new KeyValuePair<string, string>(item.Key, item.Value)).ToDictionary(x => x.Key, x => x.Value);
}

Wednesday, 11 December 2019

C# - LINQ - How to Group List and Convert to Dictionary

 Dictionary<string, List<EmployeeDetails>> result = employeeInfo
                    .GroupBy(empInfo => empInfo.EmployeeName)
                    .ToDictionary(empInfo => empInfo.Key, empInfo => empInfo.ToList());

C# - Create an XML Document with LINQ to XML

using System.Xml.Linq;


XDocument ackDoc = new XDocument(new XDeclaration("1.0", "utf - 8", "true"),
    new XElement("DepartmentsDetails"
    , new XElement("Department","Technical")
    , new XElement("Department", "Finanace")
    , new XElement("Department", "Human Resource Management")
    , new XElement("Department", "Facilities")
    , new XElement("Department", "Research and Development"));

ackDoc.Save(xmlFilePath);

Output

<DepartmentsDetails>
    <Department>Technical</Department>
    <Department>Finanace</Department>
    <Department>Human Resource Management</Department>
    <Department>Facilities</Department>
    <Department>Research and Development</Department>
</DepartmentsDetails>

C# - Read XML File Using XMLReader

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Linq;

namespace XmlProgramming
{
    internal class TagReader
    {
        public string XmlFilePath { get; }
        public string XmlElementName { get; }

        public TagReader(string xmlFilePath, string xmlElementName)
        {
            XmlFilePath = xmlFilePath;
            XmlElementName = xmlElementName;
        }

        /// <summary>
        /// Read tags from the given XML file.
        /// Func helpful in passing method to the XElement.
        /// If you want to do any other operations over the elements we can pass the function to this. 
        /// </summary>
        /// <returns></returns>
        public IEnumerable<T> Read<T>(Func<XElement,T> func)
        {
            using (FileStream fs = new FileStream(XmlFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using (XmlReader reader = XmlReader.Create(fs, GetXmlSettings()))
                {
                    reader.MoveToContent();

                    // Parse the file and return each of the nodes.
                    while (!reader.EOF)
                    {
                        if (reader.NodeType == XmlNodeType.Element && reader.Name == XmlElementName)
                        {
                            if (XNode.ReadFrom(reader) is XElement el)
                                yield return func(el);
                        }
                        else
                            reader.Read();
                    }
                }
            }
        }

        /// <summary>
        /// Returns Xml Reader Settings
        /// </summary>
        /// <returns></returns>
        private static XmlReaderSettings GetXmlSettings()
        {
            return new XmlReaderSettings
            {
                IgnoreComments = true,
                IgnoreProcessingInstructions = true,
                IgnoreWhitespace = true,
                XmlResolver = null,
                DtdProcessing = DtdProcessing.Parse,
                CheckCharacters = false
            };
        }
    }
}