EJS
EJS

Reputation: 1071

Replace line in file during multiple threads

I have a small csv file with about 40 lines of 30-ish characters each. I also have several slow threads going at the same time, so they will rarely attempt to access the file at the same time, however it can happen. So I need to make sure that they all wait for turn if necessary.

As I understand I can do:

string[] text = File.ReadAllLines(path);
text[23] = "replacement";
File.WriteAllLines(path, text);

But doing this I assume I'm running the risk of the file being updated by a different thread in between readAllLines and WriteAllLines.

What I want to do is something like:

using (FileStream fs = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
    StreamReader sr = new StreamReader(fs);
    StreamWriter sw = new StreamWriter(fs);
    //Replace the line
}

However I don't see a way to do something like writeAllLines with either the FileStream object or the StreamWriter object. Is there a simple way to do this, or do I need to write each line to a new file and then replace the old file?

Upvotes: 0

Views: 189

Answers (2)

CathalMF
CathalMF

Reputation: 10055

With a StreamWriter you don't need to specify to write all lines. You just write what you have. Either write to the file line by line using the WriteLine method or join your text array into one large string and write it all at once using the Write method.

As for preventing multiple threads from accessing your file at the same time you should use a lock.

public static object FileAccessLock = new object(); // Put this in a global area.

lock(FileAccessLock)
{
    string[] text = File.ReadAllLines(path);
    text[23] = "replacement";
    File.WriteAllLines(path, text);
}

The lock will allow only one thread to access that section of code at a time. All other threads will wait until it has completed.

That doesn't mean that the File.WriteAllLines method wont be locked by something else so you should handle an exception here.

Upvotes: 3

Igor Quirino
Igor Quirino

Reputation: 1195

You need to lock write to only one thread access. Like this:

public class FileHelper
{
    private static object fileLock  = new object();
    public static void ReplaceLine(string path, int line, string replace)
    {
        lock(fileLock)
        {
            string[] text = File.ReadAllLines(path);
            text[line] = replace;      
            File.WriteAllLines(path, text);
        } 
    } 
} 

Upvotes: 1

Related Questions