C# - Write line if line doesn't exist

620 views Asked by At

I'm trying to write a line in a CSV file as a string if the exact string doesn't exist in the CSV file already. My code works fine for me when I don't check if the line exists.

My current code looks as the following and just doesn't seem to work.

string output = @"output.csv";
TextWriter tw = new StreamWriter(output);

foreach (var player in replay.Players.OrderByDescending(i => i.IsWinner))
{
    using (StreamReader sr = new StreamReader(output))
    {
        string contentsToRead = File.ReadAllText(output);
        string contentsToWrite = replay.ReplayBuild + "," + replay.Map;
        if (!contentsToRead.Contains(contentsToWrite))
            tw.WriteLine(contentsToWrite);
        sr.Close();
    }
}
tw.Close();

I am totally new to C# and programming in general. The main work of the file I'm working on isn't mine. It's originally from https://github.com/barrett777/Heroes.ReplayParser

It totally works, at least for my understanding, if I comment out the StreamReader and only use the Write line.

I would really appreciate any kind of help and tips on how I can improve. Thanks in advance.

2

There are 2 answers

2
Itay Podhajcer On

Try reading the content of the file before opening it for writing (before the new StreamWriter(output) line).

0
Dmitry Bychenko On

I suggest using File.ReadLines as well as File.AppendAllLines. In order not to update file line by line (which can be time consuming) but in one go, I recommend Linq:

string output = @"output.csv";
...

// Hash set is effcient - O(N) - for testing if line exists or not  
HashSet<String> existingLines = new HashSet<String>(File
  .ReadLines(output));

//TODO: please, check this selection (I'm not sure in ReplayBuild and Map attributes) 
var toAppend = replay
  .Players
  .Select(player => new {
     toWrite = string.Join(",", player.ReplayBuild, player.Map),
     isWinner = player.IsWinner })
  .Where(item => existingLines.Contains(item.toWrite))
  .OrderByDescending(item => item.isWinner)
  .Select(item => item.toWrite)
  .ToList(); // since we're writing into the same file, we have to materialize

// Do we have anything to write?
if (toAppend.Any())
  File.AppendAllLines(output, toAppend);