Add a single line to the top of text file
-
06-03-2021 - |
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
Solution
You need to rewrite the whole file.
- open a new (temporary!) file
- write header line
- for each input line, write line (consider block buffering if performance is a concern)
- flush and close output file
- 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()