I have a text file containing some information that I want to edit. The file looks something like this:
id: 31
name: Anna
profession: Doctor
I can read that entry with a StreamReader
, and present it in my application. I then want the user to be able to change the name
and profession
of an entry, so I'd like to edit these specific rows to the new values, while keeping id
intact (in my real code, there's not just a few rows, but a lot of rows where only some should be changed). So, for example, I want the file, at the end of my operation, to look like this.
id: 31
name: Emma
profession: Programmer
However, I also have to take into account that sometimes the rows don't exist beforehand. For example, before editing Anna
to Emma
, it's not certain that she had a profession, the file could have looked like this:
id: 31
name: Anna
And in that case, I want to add the line profession: Programmer
to the end there.
I tried using a FileStream
with ReadWrite
access, that I give to a StreamReader
and a StreamWriter
, but then I found no way of changing or replacing a line of text, only reading it and writing a new identical line while keeping the old.
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
using (StreamReader reader = new StreamReader(fileStream))
using (StreamWriter writer = new StreamWriter(fileStream))
{
bool idExists = false;
bool nameExists = false;
bool tagsExist = false;
string line;
while((line = reader.ReadLine()) != null)
{
if (line.StartsWith("id:"))
idExists = true;
else if (line.StartsWith("name:"))
{
nameExists = true;
line = $"name: {entryToSave.Name}";
writer.WriteLine(line); // Will write an additional line and not replace
}
else if (line.StartsWith("profession:"))
{
professionExists = true;
line = $"profession: {entryToSave.Profession}";
writer.WriteLine(line); // Will write an additional line and not replace
}
}
if (!idExists)
writer.WriteLine($"id: {generatedId}");
if (!nameExists)
writer.WriteLine($"name: {entryToSave.Name}");
if (!professionExists)
writer.WriteLine($"profession: {entryToSave.Profession}");
}
I also tried using File.ReadAllLines
, loop through the lines, and then write back all the lines to the file, only modifying the lines that were to be modified. However, I don't have access to the file through File.WriteAllLines
for some reason that I don't understand, as a StreamWriter
has access. Code:
var previousData = File.ReadAllLines(filePath);
var newData = new List<string>();
bool idExists = false;
bool nameExists = false;
bool professionExists = false;
for (int i = 0; i < previousData.Length; i++)
{
var line = previousData[i];
if (line.StartsWith("id:")
idExists = true;
else if (line.StartsWith("name:")
{
nameExists = true;
line = $"name: {entryToSave.Name}";
}
else if (line.StartsWith("profession:"))
{
professionExists = true;
line = $"profession: {entryToSave.Profession}";
}
newData.Add(line);
}
if (!idExists)
newData.Add($"id: {generatedId}");
if (!nameExists)
newData.Add($"name: {entryToSave.Name}");
if (!professionExists)
newData.Add($"profession: {entryToSave.Profession}");
File.WriteAllLines(filePath, newData.ToArray()); // Access denied
How is this most easily achieved, without file streams interfering with each other?