Click here to Skip to main content
Click here to Skip to main content
Go to top

String Replace and File Handling library

, 8 Jan 2008
Rate this:
Please Sign up or sign in to vote.
Library which contains code for replacing some of the Text in files based on conditions and handling the files by reading and writing strings from or to the file by recursively browsing the folder.

Introduction

The article is mainly for beginners of .NET programming, who will be in need of creating some UI Tools/Console application for replacing some of the Text in various files based on their needs. I have written a TextReplaceIO Library, includes DirectoryHandler and a StringReplaceHelper class which will be helpful for the purpose of StringReplacement in a text file based on the user conditions by recursively browsing through the folder. I also created a simple StringReplaceTool sample using the DirectoryHandler and StringReplaceHelper class, where anyone can create a Search and Replace Tool for their needs with very little code. I didn't get more time to spend on the sample, to make it better, and illustrate all the functionality. However, if anyone needs a specific sample for explaining any functionality, please email me.

Background

During my earlier development on Custom controls, and Website Development, I came across many situations where I was in need of replacing the version numbers during each build performed. So, I thought of having a library which will help to handle such scenarios (However, I haven't used or tested this library in more scenarios now).

Using the Code

About TextReplaceIO Namespace

The namespace consists of two classes, one for handling the operations on files and folder and another for replacing strings in various conditions.

DirectoryHandler

This class is used for handling the following operations on files and folders:

  1. Reading text files as string. The below method is used for this purpose:

    /// <summary>
    /// Read the contents of the specified file and return it as a string.
    /// </summary>
    /// <remarks>
    /// If you try to read unsupported file types, and then save the 
    /// file, some files might get corrupted. so make sure to only  
    ///open and write supported files.
    /// </remarks>
    /// <param name=""nextFile"">File that needs to be read</param>
    public string ReadFileContents(FileInfo nextFile)
    {
        // updating the variable about the file that is reading.
        this.processingFileInFo = nextFile;
        FileStream fs = new FileStream(nextFile.FullName, 
    			FileMode.OpenOrCreate, FileAccess.ReadWrite);
        StreamReader sr = new StreamReader(fs);
        String fileString = sr.ReadToEnd();
        sr.Close();
        fs.Close();
        return fileString;
    }
  2. Writing string to text files. The following method is used for this purpose:

    /// <summary>
    /// Write the string contents to a text file.
    /// </summary>
    /// <param name=""strWrite"">string to be written on the file</param>
    /// <param name=""filePath"">Path in which the string has to be written as a file
    /// </param>
    /// <param name=""fileMode""><see cref="FileMode"" /></param>
    public void WriteContentsToFile
    	(string strWrite, string filePath, FileMode fileMode)
    {
        String newFileString = strWrite;
        FileStream fs = new FileStream(filePath, fileMode, FileAccess.Write);
        StreamWriter sw = new StreamWriter(fs);
        sw.Write(newFileString);
        sw.Close();
        fs.Close();
    }
  3. Populate a treeview with System drives and load sub nodes on demand. (Actually, I got some core ideas from some other article, but am not able to find it now.). In the DirectoryHandler class, you have to use CreateTreeViewDirectory(TreeView treeView) for loading the drives into the TreeNode. A special folder Desktop type is added in the list, as it is a commonly used special folder. You need to call the following method in the BeforeExpand event of 'Treeview' for loading the treeview nodes on demand. LoadDirectoryinTreeViewOnDemand(TreeNode parentNode) method is added in the DirectoryHandler as many developers like to do their file/folder operations by selecting from a treeview.

  4. Parse through all files and folders recursively based on filter conditions, and get the files using the ManipulateFilteredFile event.
    The following methods are used for this:

    /// <summary>
    /// Parse through all the folders in the specified directory 
    /// </summary>
    /// <param name=""dirInfo"">Provide the directory which needs to be parsed</param>
    /// <param name=""recursive"">Setting this to 'True' 
    /// will parse through all the subfolders in the directory.</param>
    public void ParseFolder(DirectoryInfo dirInfo, bool recursive)
    {
        DirectoryInfo[] subDirs;
        FileInfo[] files;
        ResetOriginal();
        //Getting filelist of parent directory
        ListContentsOfFolder(dirInfo);
               
        foreach (DirectoryInfo directory in dirInfo.GetDirectories())
        {
            if (directory != null && directory.Exists)
            {
                this.dirCount += 1;
                subDirs = directory.GetDirectories();
                files=directory.GetFiles();
                if (recursive && subDirs.Length != 0)
                {
                    //Getting file list of SubDirectories.
                    ListContentsOfFolder(directory);
                    ParseSubFolder(directory, true);
                }
                else if (recursive && files.Length > 0)
                {
                    //Getting file list of SubDirectories.
                    ListContentsOfFolder(directory);
                }
            }
        }
    }
    
    /// <summary>
    /// Parse through the contents of each folders
    /// </summary>
    /// <param name=""Parent""></param>
    protected void ListContentsOfFolder(DirectoryInfo Parent)
    { 
        foreach (FileInfo NextFile in Parent.GetFiles())
        {
            this.fileCount += 1;
            if (this.FilteredFileTypes == null&& this.FilterFileNames==null)
            {
                this.filterFileCount += 1;
                OnManipulateFilteredFile(NextFile);
            }
            else
            {
                bool filteredFile = CheckForFilter(NextFile);
                if (filteredFile)
                {
                    this.filterFileCount += 1;
                    OnManipulateFilteredFile(NextFile);
                }
            }
        }
    }
    
    /// <summary>
    /// Raises the ManipulateFilteredFile event.
    /// </summary>
    /// <param name=""NextFile"">FileInfo</param>
    public virtual void OnManipulateFilteredFile(FileInfo NextFile)
    {
        ManipulateFilteredFile(this, NextFile);        
    }
  5. The ChangeEvents method is used for creating log files if a folder or file is changed, deleted or modified. Set the LogFileName property, in which the log files need to be written.

    /// <summary>
    /// Updates if there are any changes in the files in the  specified directory. 
    /// The changes will be appended to the file, if you set the LogFileName Property.
    /// </summary>
    /// <remarks>The User needs to create/clean the log file before he uses these 
    /// events based on the needs as the contents are only appended using this approach
    /// </remarks>
    /// <param name=""fsw"">The Folder that needs to be watched for changes</param>
    public void ChangeEvents(FileSystemWatcher fsw, bool enableRaisingEvents)
    {
        fsw.Changed += new FileSystemEventHandler(fsw_Changed);
        fsw.Deleted += new FileSystemEventHandler(fsw_Deleted);
        fsw.Created += new FileSystemEventHandler(fsw_Created);
        fsw.Renamed += new RenamedEventHandler(fsw_Renamed);
        fsw.EnableRaisingEvents = true;
    }
    void fsw_Renamed(object sender, RenamedEventArgs e)
    {
        WriteContentsToFile(String.Format("\r\nRenamed {0} to {1}", 
    		e.OldName, e.Name), this.LogFileName, FileMode.Append);
    }
    ………………………..
    …………………………….

StringReplaceHelper

This class is used for replacing String based on the following conditions:

  1. Find a specific string and replace it with another string
  2. Find a specific string and replace it with another string, if the strings are in between a specified block
  3. Replace entire string within a specified string
  4. Replace the entire string within a specified string if the strings are in between a specified block
  5. Replace a string if and only if it is found before or after a specific string

All the above conditions, except (4) are implemented in ReplaceStringWithCondition method (i.e., a function call will be done in this method, in which based on the parameters, the ReplaceStringWithCondition function will be executed) and (4) is implemented in the ReplaceStringBetweenWithCondition method. For now, I have used two different types of logic to get the strings that need to be searched for replace conditions in each of the above mentioned methods. By further modification, this can be further simplified. I will try to do it later if I get some time to spend on this:

  1. In ReplaceStringWithCondition, I used the inbuilt string.split method to split the entire string based upon the StartWith or EndsWith string as the Tokenizer, and then after modifying the string, I will merge the Tokenizers also along with the strings.
  2. In ReplaceStringBetweenWithCondition to get the string that needs to be checked for replacing some of the contents in it, I have split by finding the index of the provided string block.

About StringReplaceSample

The sample explains almost all the functionalities of the TextReplaceIO library, which is mentioned in the TextReplaceIO section. You can use only some of the methods in your console application or any other application based on your need. Use the sample in the following way. See the code inside the sample for you to get more ideas on the implementations.

Step1

Select the File/Folder, from the Treeview, in which you want some of the strings of some files inside the directory that need to be replaced.

Treeview.gif

Step2

Provide the Filter condition of files that needs to be searched either by giving FileName or by Filetype or both.

File Filter condition

Step3

Then based upon the condition to replace, fill the Textboxes and click the corresponding button for required operations:

  1. For simply replacing some string in all the Filtered files, specify the "String to be replaced" and "Replace With" TextBox and click replace.

    simple replacement

  2. For replacing some string in the entire filtered file, whereas, the string is found in between specified strings, provide 'StartSearch' and 'EndSearch':

    Replace with condition

  3. For replacing a string found anywhere before a specified string, provide 'StartSearch' TextBox alone, and click on the button.
  4. For Inserting/Replace entire string within some Strings, follow the below steps:
    1. It is essential to provide String replace with TextBox, in the "General String Replacement Group"
    2. Specify 'StartString' and 'EndString' TextBox.
    3. Click on the Button below this textboxes, so that the contents within the StartString and EndString will be replaced.

      Replace entire String

  5. For Inserting/Replace entire string if it is available within specified string blocks.
      Along with the Steps in Operation(4), include the StartBlock and 'EndBlock', then click the button.

    Replace entire String

  6. Inserting some string in the top or bottom of the file is achieved by using the following code in the sample using the string.insert method. The modified string is written into the file using the WriteContentsToFile Method, which is called inside the ReplaceStringandWriteToFile method.

Conclusion

I'm sure some of the Regex programmers are going to have a better way, some others might use the StringBuilder class for this to be done for performance reasons. But, I hope someone will find my program useful. As there are possibilities for adding a lot more extended functionality, if you are in need of any such functionality or code changes for some reason, please feel free to contact me, so that I can add those. Thanks for reading.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sivastyle
Web Developer
India India
I am a software developer from Chennai, India. From Novemeber 2004, I am in to the .NET Framework and I enjoy writing codes in C#. My experience in .NET Technology includes designing and creating custom controls and application for Web and windows platform.

Comments and Discussions

 
Generaltest PinmemberSivastyle15-May-08 22:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 8 Jan 2008
Article Copyright 2007 by Sivastyle
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid