yosafat
yosafat

Reputation: 253

C# How to append only the end of text file and in specific position?

i want to change status from OK to NG,

IPen ID     Datetime                                Status
50      Wednesday, September 21, 2016 08:56:45      OK
IPen ID     Datetime                                Status
50      Wednesday, September 21, 2016 08:56:51      OK

this is file on my report.txt. my expectation is how we delete this last line with c# ?

IPen ID     Datetime                                Status
50      Wednesday, September 21, 2016 08:56:51      OK

and how to append OK status change into NG status? the result i hope is like this :

IPen ID     Datetime                                Status
50      Wednesday, September 21, 2016 08:56:45      NG

this is my code :

var lines = File.ReadAllLines(Fullpath);
File.WriteAllLines(Fullpath, lines.Take(lines.Length - 1).ToArray());
DisplayData(MessageType.Incoming, lines[lines.Length - 1]);

var text = new StringBuilder();

foreach (string s in File.ReadAllLines(Fullpath))
{
    text.AppendLine(s.Replace("OK", "NG"));
}

using (var file = new StreamWriter(File.Create(Fullpath)))
{
    file.Write(text.ToString());
}

this code will append all of "OK" change into "NG". not like that i want, but i want to delete the last result and change only two last result from "OK" to "NG" not all OK change to NG. any suggestion or solution for me? thanks for attention and help.

Upvotes: 3

Views: 320

Answers (4)

Onel Sarmiento
Onel Sarmiento

Reputation: 1626

Instead of updating all lines, determine the last line and then update.

var lines = File.ReadAllLines(Fullpath);
File.WriteAllLines(Fullpath, lines.Take(lines.Length - 1).ToArray());
DisplayData(MessageType.Incoming, lines[lines.Length - 1]);

var text = new StringBuilder();
var data = File.ReadAllLines(Fullpath);
var lines = data.Take(data.Count() - 2);
var last = lines.Last();

foreach (string s in lines)
{
    if(s.Equals(last))
    {
        text.AppendLine(s.Replace("OK", "NG"));
    }
    else
    {
        text.AppendLine(s);
    }
}

using (var file = new StreamWriter(File.Create(Fullpath)))
{
    file.Write(text.ToString());
}

enter image description here

Upvotes: 2

BenVlodgi
BenVlodgi

Reputation: 2185

You can't "Append" Over something.

You need to read in the whole file into an array of strings (one for each line) then alter the lines you want, then re-write the whole contents over the existing file.

// Read in whole contents of file.
var lines = File.ReadAllLines(Fullpath);

// Alter the lines you want to.
//Remove the last two rows (headers and data)
if (lines.Length > 2) lines = lines.ToList().Take(lines.Length - 2).ToArray();

// If lines contains 1 or more line in the file, replace any occurrence of OK, with NG.
if (lines.Length >= 1) lines[lines.Length - 1] = lines[lines.Length - 1].Replace("OK", "NG");

// Now write the contents of the file you have here in RAM back over the original file.
File.WriteAllLines(Fullpath, lines);

I would suggest a more robust way of editing these logs. It would be problematic if the records being written were later changed to include two columns that wrote out a value of OK. In this case, you would alter them both. Alternatives to this are:

  • As @keith-nicholas suggested, seriealize your data into an object and use that for editing.
  • Or get the column starting location from the line above the line you are editing. Then use that as a reference point. For Instance, to edit the last line:

    // This assumes those column headers are above each line
    if (lines.Length >= 2)
    {
        // Get the string starting location of the [Status] column
        int index = lines[lines.Length - 2].IndexOf("Status");
    
        // Now replace the text under that Status Column in the next row
        // Remove the OK characters (first two)
        lines[lines.Length - 1] = lines[lines.Length - 1].Remove(index, 2);
        // Then Insert the two characters you want
        lines[lines.Length - 1] = lines[lines.Length - 1].Insert(index, "NG");
    }
    

Upvotes: 1

Jacob
Jacob

Reputation: 746

Since you're already reading the entire file into memory, you could convert it to a list, remove from the end, and iterate in reverse to update the last two entries:

var lines = File.ReadAllLines(Fullpath).ToList();

// Remove as many lines as you'd like from the end
if (lines.Count > 2)
{
    lines.RemoveRange(lines.Count - 2, 2);
}

// Iterate backwards through the list until we've updated 2 (or more or less) lines
var linesUpdated = 0;

for (var i = lines.Count - 1; i >= 0 && linesUpdated < 2; i--)
{
    if (lines[i].Contains("OK"))
    {
        lines[i] = lines[i].Replace("OK", "NG");
        linesUpdated++;
    }
}

File.WriteAllLines(Fullpath, lines.ToArray());

Upvotes: 2

Keith Nicholas
Keith Nicholas

Reputation: 44298

simplistic approach :-

var lines = File.ReadAllLines(path);
if (lines.Length > 0)
{
  lines[lines.Length - 1] = lines[lines.Length - 1].Replace("OK", "NG");
}
File.WriteAllLines(path, lines);

to remove last two lines

File.WriteAllLines(path, File.ReadAllLines(path).ToList().Take(lines.Count-2).ToArray())

But you probably want to start parsing the lines into objects, make whatever changes to your objects, then serializing them back out as lines of text

Upvotes: 1

Related Questions