Replace data in file C#

There was one of the requirement to find and replace the data from the file. First we have written code to load all the data in the variable and then replace it. But it will be a problem with a huge files. So we wrote two methods to replace it line by line or chunk by chunk. Both of these methods are written below. These methods although seems correct to us but not tested. If any problem do reply back so that it can be modified

Download sample from FileFindReplace Sample

public class FileFindRelpace    
{
/// 
/// Replace the data in the Huge files searching and replacing chunk        
/// by chunk. It will create new file as filepath + ".tmp" file with        
/// replaced data        
/// 
/// Path of the file
/// Text to be replaced
/// Text with which it is replaced        
public void ReplaceLineByLine(string filePath, string replaceText, string withText)
{
StreamReader streamReader = new StreamReader(filePath);
StreamWriter streamWriter = new StreamWriter(filePath + ".tmp");

while (!streamReader.EndOfStream)
{
string data = streamReader.ReadLine();
data = data.Replace(replaceText, withText);
streamWriter.WriteLine(data);
}

streamReader.Close();
streamWriter.Close();
}

/// 
/// Replace the data in the Huge files searching and replacing chunk        
/// by chunk. It will create new file as filepath + ".tmp" file with        
/// replaced data        
/// 
/// Path of the file
/// Text to be replaced
/// Text with which it is replaced
/// Length of the data to be loaded at one go        
public void ReplaceByChunk(string filePath, string replaceText, string withText, int chunkLength)
{
int loadLength = chunkLength + replaceText.Length;
char[] buffer = new char[loadLength];
int index = 0;
int replaceLength = replaceText.Length;

StreamReader streamReader = new StreamReader(filePath);
StreamWriter streamWriter = new StreamWriter(filePath + ".tmp");

//Load the data according to the chunk length specified
//also load the extra data according to the length of
//the replace text so that chunk end and start text break
//can be handled            
while(true)
{
//Seek to the position from where we want to start and
//load the data in to the memory
                streamReader.DiscardBufferedData();
streamReader.BaseStream.Seek(index, SeekOrigin.Begin);
int count = streamReader.ReadBlock(buffer,0,loadLength);
if (count == 0) break;

//Get the data and check whether the extra loaded data
//is replaceable if yes then set end replaced flag                
string data = ConvertToString(buffer, count);
bool isEndReplaced = false;
if(count >= chunkLength)
isEndReplaced = (data.LastIndexOf(withText, chunkLength) > 0);

//Replace the data with the specified data and save the
//new data in the new file
                data = data.Replace(replaceText, withText);
if(isEndReplaced)
{
streamWriter.Write(data);
index += count;
}
else                
{
if (count >= chunkLength)
{
streamWriter.Write(data.Substring(0, data.Length - replaceLength));
index += chunkLength;
}
else                    
{
streamWriter.Write(data);
index += chunkLength;
}
}
}

streamReader.Close();
streamWriter.Close();
}

private string ConvertToString(char[] buffer, int count)
{
StringBuilder data = new StringBuilder(buffer.Length);

for (int i = 0; i < count; i++)
{
data.Append(buffer[i]);
}

return data.ToString();
}
}
About these ads
8 comments
  1. peace said:

    I have a 1.6GB size xml file wherein i have to find/replace strings. The above code doesn’t really work with the offset logic as stream writer writer few extra bytes of information making the xml useful. So then i took your replacebyline function & manipulated on it.It works now! So thanks for the article, atleast i got an idea where to start.

    • Vinay said:

      Hi peace,
      What is the modification you have done to the code ?. Can you post the updated code ?. I need to find and replace in a huge XMl file. That my XML files have German and Jaapnese charecters :)

      • A.Sethi said:

        Sure i will upload the latest code for you. but i don’t know whether it will work for german and japnese characters

  2. Patrick said:

    I am new to c# but this is exactly what I need to do, but I want to save the file as the original filename. How can I do that?

    I tried removing the ,tmp code but I always receive a file in use error when attempting it now.

    • A.Sethi said:

      Patrick

      What you can do is when we are opening stream reader for the source file, read all the data in the string variable by using streamReader.ReadToEnd() and then close the stream reader first. After that open the stream writer with same name and then do the replacement of the text in that string and save it in the same file again. But if it is a huge file then this can become slow and consume too much memory in one go since we are loading all the data in one time

      Otherwise what you can do is that in the existing code itself after closing the reader and writer object. Replace the main file with tmp file

  3. codingsense said:

    Hi,

    Thanks for the nice article :). The only change that i suggest is instead of using ConvertToString method we can convert char arrary to string as
    string CharToString = new string(buffer);

    Thanks,
    Codingsense

    • A.Sethi said:

      Thanks for the suggestion will update the post with suggested code

  4. Paul said:

    What if the string to replace is split up by the chunks? I.e. If I have a large block of text to replace inside the large file, and the split happens to be in the middle of it, the replace won’t work since it won’t find the string to replace… any suggestions?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: