Question

My app pulls data and appends it to a text file but I need to find out how I can programmatically look at the first line of the text file and see if it matches the following text:

DateTime,VirtualIP,VirtualPort,VirtualName,DestinationIP,DestPort,Status,Desired

If it does then continue doing the normal function (snippet below), if the first line is not the same as above then I want to insert the above in the first line without overwriting whats currently there. How can I do this? (essentially pushing everything one line down so I can add what I want on the first line)...btw this is being saved as a csv file that can be opened in excel.

try
{
    // ...
    for (int j = 0; j < memberStatus.Result.Count; j++)
    {
        VirtualMemberStatus status = memberStatus.Result[j];

        //text += String.Format("Name: {4}, Member: {0}:{1}, Status: {2}, Desired: {3}" + Environment.NewLine, status.Member.Address, status.Member.Port, status.EffectiveStatus, status.DesiredStatus, virtualKey.Key);
        text += String.Format("{5},{4},{0},{1},{2},{3}" + Environment.NewLine, status.Member.Address, status.Member.Port, status.EffectiveStatus, status.DesiredStatus, virtualKey.Key.Replace(":", ","), DateTime.UtcNow);
    }
}
catch
{
    //ERROR CODE 2
    //MessageBox.Show("Error occurred, check device name (case senstive) and admin group. This error may also occur due to connection loss, try again.");
    errors += String.Format("{0} Error Code: 2, Error occurred, check device name (case senstive) and admin group. This error may also occur due to connection loss, try again." + Environment.NewLine, DateTime.UtcNow);

}

this.resultsTextBox.Text = text;

This file does not get deleted a lot but in the event that it does I want it to have the correct column names at the top. ie:

DateTime,VirtualIP,VirtualPort,VirtualName,DestinationIP,DestPort,Status,Desired
Was it helpful?

Solution

You need to rewrite the whole file.

  1. open a new (temporary!) file
  2. write header line
  3. for each input line, write line (consider block buffering if performance is a concern)
  4. flush and close output file
  5. ONLY if there were no errors, move the temporary file in-place (by renaming).

This procedure can prevent problems when there is an (IO) error halfway the process

Here is code to do such a thing:

using (var input = new StreamReader("input.txt"))
    using (var output = new StreamWriter("input.txt.temp"))
{
    output.WriteLine("headerline"); // replace with your header :)

    var buf = new char[4096];
    int read = 0;
    do 
    {
        read = input.ReadBlock(buf, 0, buf.Length);
        output.Write(buf, 0, read);
    } while (read > 0);

    output.Flush();
    output.Close();
    input.Close();
}

File.Replace("input.txt.temp", "input.txt", "input.txt.backup");

Note that the sample code even creates a backup. One possible point of improvement would be to explicitely instantiate FileStream(...., FileMode.CreateNew) so as to prevent overwriting the temporary file if a file already exists by that name.

Another solution to that would be, to use System.IO.Path.GetTempFileName(). However, then File.Replace might no longer be efficient and atomic, because the tempfolder might be on another volume/filesystem.

OTHER TIPS

you need to search to first position to see if it mathches those words, this code snippet can achive what you are looking for.

    Dim filePath As String = "file.txt"
    Dim bufferSize As Integer = 8129

    Dim textToMatch As String = "DateTime,VirtualIP,VirtualPort,VirtualName,DestinationIP,DestPort,Status,Desired"
    Dim textByte As Byte() = ASCIIEncoding.ASCII.GetBytes(text)

    Dim buffer As Byte() = Nothing

    Dim fs As FileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite)
    fs.Read(buffer, 0, bufferSize)


    Dim i As Int32 = fs.Seek(0, SeekOrigin.Begin)
    fs.Position = i

    If fs.Position.Equals(textToMatch) Then

    Else
        fs.Write(textByte, 0, textByte.Length)
    End If

    fs.Flush()
    fs.Close()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top